xfrm: Add a dummy network device for napi.
[linux-2.6-block.git] / drivers / net / ethernet / mellanox / mlxsw / switchx2.c
1 /*
2  * drivers/net/ethernet/mellanox/mlxsw/switchx2.c
3  * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
4  * Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com>
5  * Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com>
6  * Copyright (c) 2015-2016 Elad Raz <eladr@mellanox.com>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the names of the copyright holders nor the names of its
17  *    contributors may be used to endorse or promote products derived from
18  *    this software without specific prior written permission.
19  *
20  * Alternatively, this software may be distributed under the terms of the
21  * GNU General Public License ("GPL") version 2 as published by the Free
22  * Software Foundation.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36
37 #include <linux/kernel.h>
38 #include <linux/module.h>
39 #include <linux/types.h>
40 #include <linux/pci.h>
41 #include <linux/netdevice.h>
42 #include <linux/etherdevice.h>
43 #include <linux/slab.h>
44 #include <linux/device.h>
45 #include <linux/skbuff.h>
46 #include <linux/if_vlan.h>
47 #include <net/switchdev.h>
48
49 #include "pci.h"
50 #include "core.h"
51 #include "reg.h"
52 #include "port.h"
53 #include "trap.h"
54 #include "txheader.h"
55 #include "ib.h"
56
57 static const char mlxsw_sx_driver_name[] = "mlxsw_switchx2";
58 static const char mlxsw_sx_driver_version[] = "1.0";
59
60 struct mlxsw_sx_port;
61
62 struct mlxsw_sx {
63         struct mlxsw_sx_port **ports;
64         struct mlxsw_core *core;
65         const struct mlxsw_bus_info *bus_info;
66         u8 hw_id[ETH_ALEN];
67 };
68
69 struct mlxsw_sx_port_pcpu_stats {
70         u64                     rx_packets;
71         u64                     rx_bytes;
72         u64                     tx_packets;
73         u64                     tx_bytes;
74         struct u64_stats_sync   syncp;
75         u32                     tx_dropped;
76 };
77
78 struct mlxsw_sx_port {
79         struct net_device *dev;
80         struct mlxsw_sx_port_pcpu_stats __percpu *pcpu_stats;
81         struct mlxsw_sx *mlxsw_sx;
82         u8 local_port;
83         struct {
84                 u8 module;
85         } mapping;
86 };
87
88 /* tx_hdr_version
89  * Tx header version.
90  * Must be set to 0.
91  */
92 MLXSW_ITEM32(tx, hdr, version, 0x00, 28, 4);
93
94 /* tx_hdr_ctl
95  * Packet control type.
96  * 0 - Ethernet control (e.g. EMADs, LACP)
97  * 1 - Ethernet data
98  */
99 MLXSW_ITEM32(tx, hdr, ctl, 0x00, 26, 2);
100
101 /* tx_hdr_proto
102  * Packet protocol type. Must be set to 1 (Ethernet).
103  */
104 MLXSW_ITEM32(tx, hdr, proto, 0x00, 21, 3);
105
106 /* tx_hdr_etclass
107  * Egress TClass to be used on the egress device on the egress port.
108  * The MSB is specified in the 'ctclass3' field.
109  * Range is 0-15, where 15 is the highest priority.
110  */
111 MLXSW_ITEM32(tx, hdr, etclass, 0x00, 18, 3);
112
113 /* tx_hdr_swid
114  * Switch partition ID.
115  */
116 MLXSW_ITEM32(tx, hdr, swid, 0x00, 12, 3);
117
118 /* tx_hdr_port_mid
119  * Destination local port for unicast packets.
120  * Destination multicast ID for multicast packets.
121  *
122  * Control packets are directed to a specific egress port, while data
123  * packets are transmitted through the CPU port (0) into the switch partition,
124  * where forwarding rules are applied.
125  */
126 MLXSW_ITEM32(tx, hdr, port_mid, 0x04, 16, 16);
127
128 /* tx_hdr_ctclass3
129  * See field 'etclass'.
130  */
131 MLXSW_ITEM32(tx, hdr, ctclass3, 0x04, 14, 1);
132
133 /* tx_hdr_rdq
134  * RDQ for control packets sent to remote CPU.
135  * Must be set to 0x1F for EMADs, otherwise 0.
136  */
137 MLXSW_ITEM32(tx, hdr, rdq, 0x04, 9, 5);
138
139 /* tx_hdr_cpu_sig
140  * Signature control for packets going to CPU. Must be set to 0.
141  */
142 MLXSW_ITEM32(tx, hdr, cpu_sig, 0x04, 0, 9);
143
144 /* tx_hdr_sig
145  * Stacking protocl signature. Must be set to 0xE0E0.
146  */
147 MLXSW_ITEM32(tx, hdr, sig, 0x0C, 16, 16);
148
149 /* tx_hdr_stclass
150  * Stacking TClass.
151  */
152 MLXSW_ITEM32(tx, hdr, stclass, 0x0C, 13, 3);
153
154 /* tx_hdr_emad
155  * EMAD bit. Must be set for EMADs.
156  */
157 MLXSW_ITEM32(tx, hdr, emad, 0x0C, 5, 1);
158
159 /* tx_hdr_type
160  * 0 - Data packets
161  * 6 - Control packets
162  */
163 MLXSW_ITEM32(tx, hdr, type, 0x0C, 0, 4);
164
165 static void mlxsw_sx_txhdr_construct(struct sk_buff *skb,
166                                      const struct mlxsw_tx_info *tx_info)
167 {
168         char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN);
169         bool is_emad = tx_info->is_emad;
170
171         memset(txhdr, 0, MLXSW_TXHDR_LEN);
172
173         /* We currently set default values for the egress tclass (QoS). */
174         mlxsw_tx_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_0);
175         mlxsw_tx_hdr_ctl_set(txhdr, MLXSW_TXHDR_ETH_CTL);
176         mlxsw_tx_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH);
177         mlxsw_tx_hdr_etclass_set(txhdr, is_emad ? MLXSW_TXHDR_ETCLASS_6 :
178                                                   MLXSW_TXHDR_ETCLASS_5);
179         mlxsw_tx_hdr_swid_set(txhdr, 0);
180         mlxsw_tx_hdr_port_mid_set(txhdr, tx_info->local_port);
181         mlxsw_tx_hdr_ctclass3_set(txhdr, MLXSW_TXHDR_CTCLASS3);
182         mlxsw_tx_hdr_rdq_set(txhdr, is_emad ? MLXSW_TXHDR_RDQ_EMAD :
183                                               MLXSW_TXHDR_RDQ_OTHER);
184         mlxsw_tx_hdr_cpu_sig_set(txhdr, MLXSW_TXHDR_CPU_SIG);
185         mlxsw_tx_hdr_sig_set(txhdr, MLXSW_TXHDR_SIG);
186         mlxsw_tx_hdr_stclass_set(txhdr, MLXSW_TXHDR_STCLASS_NONE);
187         mlxsw_tx_hdr_emad_set(txhdr, is_emad ? MLXSW_TXHDR_EMAD :
188                                                MLXSW_TXHDR_NOT_EMAD);
189         mlxsw_tx_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL);
190 }
191
192 static int mlxsw_sx_port_admin_status_set(struct mlxsw_sx_port *mlxsw_sx_port,
193                                           bool is_up)
194 {
195         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
196         char paos_pl[MLXSW_REG_PAOS_LEN];
197
198         mlxsw_reg_paos_pack(paos_pl, mlxsw_sx_port->local_port,
199                             is_up ? MLXSW_PORT_ADMIN_STATUS_UP :
200                             MLXSW_PORT_ADMIN_STATUS_DOWN);
201         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(paos), paos_pl);
202 }
203
204 static int mlxsw_sx_port_oper_status_get(struct mlxsw_sx_port *mlxsw_sx_port,
205                                          bool *p_is_up)
206 {
207         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
208         char paos_pl[MLXSW_REG_PAOS_LEN];
209         u8 oper_status;
210         int err;
211
212         mlxsw_reg_paos_pack(paos_pl, mlxsw_sx_port->local_port, 0);
213         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(paos), paos_pl);
214         if (err)
215                 return err;
216         oper_status = mlxsw_reg_paos_oper_status_get(paos_pl);
217         *p_is_up = oper_status == MLXSW_PORT_ADMIN_STATUS_UP ? true : false;
218         return 0;
219 }
220
221 static int __mlxsw_sx_port_mtu_set(struct mlxsw_sx_port *mlxsw_sx_port,
222                                    u16 mtu)
223 {
224         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
225         char pmtu_pl[MLXSW_REG_PMTU_LEN];
226         int max_mtu;
227         int err;
228
229         mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sx_port->local_port, 0);
230         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmtu), pmtu_pl);
231         if (err)
232                 return err;
233         max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl);
234
235         if (mtu > max_mtu)
236                 return -EINVAL;
237
238         mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sx_port->local_port, mtu);
239         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(pmtu), pmtu_pl);
240 }
241
242 static int mlxsw_sx_port_mtu_eth_set(struct mlxsw_sx_port *mlxsw_sx_port,
243                                      u16 mtu)
244 {
245         mtu += MLXSW_TXHDR_LEN + ETH_HLEN;
246         return __mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu);
247 }
248
249 static int mlxsw_sx_port_mtu_ib_set(struct mlxsw_sx_port *mlxsw_sx_port,
250                                     u16 mtu)
251 {
252         return __mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu);
253 }
254
255 static int mlxsw_sx_port_ib_port_set(struct mlxsw_sx_port *mlxsw_sx_port,
256                                      u8 ib_port)
257 {
258         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
259         char plib_pl[MLXSW_REG_PLIB_LEN] = {0};
260         int err;
261
262         mlxsw_reg_plib_local_port_set(plib_pl, mlxsw_sx_port->local_port);
263         mlxsw_reg_plib_ib_port_set(plib_pl, ib_port);
264         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(plib), plib_pl);
265         return err;
266 }
267
268 static int mlxsw_sx_port_swid_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 swid)
269 {
270         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
271         char pspa_pl[MLXSW_REG_PSPA_LEN];
272
273         mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sx_port->local_port);
274         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(pspa), pspa_pl);
275 }
276
277 static int
278 mlxsw_sx_port_system_port_mapping_set(struct mlxsw_sx_port *mlxsw_sx_port)
279 {
280         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
281         char sspr_pl[MLXSW_REG_SSPR_LEN];
282
283         mlxsw_reg_sspr_pack(sspr_pl, mlxsw_sx_port->local_port);
284         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sspr), sspr_pl);
285 }
286
287 static int mlxsw_sx_port_module_info_get(struct mlxsw_sx *mlxsw_sx,
288                                          u8 local_port, u8 *p_module,
289                                          u8 *p_width)
290 {
291         char pmlp_pl[MLXSW_REG_PMLP_LEN];
292         int err;
293
294         mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
295         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmlp), pmlp_pl);
296         if (err)
297                 return err;
298         *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
299         *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl);
300         return 0;
301 }
302
303 static int mlxsw_sx_port_open(struct net_device *dev)
304 {
305         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
306         int err;
307
308         err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, true);
309         if (err)
310                 return err;
311         netif_start_queue(dev);
312         return 0;
313 }
314
315 static int mlxsw_sx_port_stop(struct net_device *dev)
316 {
317         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
318
319         netif_stop_queue(dev);
320         return mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false);
321 }
322
323 static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb,
324                                       struct net_device *dev)
325 {
326         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
327         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
328         struct mlxsw_sx_port_pcpu_stats *pcpu_stats;
329         const struct mlxsw_tx_info tx_info = {
330                 .local_port = mlxsw_sx_port->local_port,
331                 .is_emad = false,
332         };
333         u64 len;
334         int err;
335
336         if (mlxsw_core_skb_transmit_busy(mlxsw_sx->core, &tx_info))
337                 return NETDEV_TX_BUSY;
338
339         if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) {
340                 struct sk_buff *skb_orig = skb;
341
342                 skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN);
343                 if (!skb) {
344                         this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped);
345                         dev_kfree_skb_any(skb_orig);
346                         return NETDEV_TX_OK;
347                 }
348         }
349         mlxsw_sx_txhdr_construct(skb, &tx_info);
350         /* TX header is consumed by HW on the way so we shouldn't count its
351          * bytes as being sent.
352          */
353         len = skb->len - MLXSW_TXHDR_LEN;
354         /* Due to a race we might fail here because of a full queue. In that
355          * unlikely case we simply drop the packet.
356          */
357         err = mlxsw_core_skb_transmit(mlxsw_sx->core, skb, &tx_info);
358
359         if (!err) {
360                 pcpu_stats = this_cpu_ptr(mlxsw_sx_port->pcpu_stats);
361                 u64_stats_update_begin(&pcpu_stats->syncp);
362                 pcpu_stats->tx_packets++;
363                 pcpu_stats->tx_bytes += len;
364                 u64_stats_update_end(&pcpu_stats->syncp);
365         } else {
366                 this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped);
367                 dev_kfree_skb_any(skb);
368         }
369         return NETDEV_TX_OK;
370 }
371
372 static int mlxsw_sx_port_change_mtu(struct net_device *dev, int mtu)
373 {
374         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
375         int err;
376
377         err = mlxsw_sx_port_mtu_eth_set(mlxsw_sx_port, mtu);
378         if (err)
379                 return err;
380         dev->mtu = mtu;
381         return 0;
382 }
383
384 static struct rtnl_link_stats64 *
385 mlxsw_sx_port_get_stats64(struct net_device *dev,
386                           struct rtnl_link_stats64 *stats)
387 {
388         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
389         struct mlxsw_sx_port_pcpu_stats *p;
390         u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
391         u32 tx_dropped = 0;
392         unsigned int start;
393         int i;
394
395         for_each_possible_cpu(i) {
396                 p = per_cpu_ptr(mlxsw_sx_port->pcpu_stats, i);
397                 do {
398                         start = u64_stats_fetch_begin_irq(&p->syncp);
399                         rx_packets      = p->rx_packets;
400                         rx_bytes        = p->rx_bytes;
401                         tx_packets      = p->tx_packets;
402                         tx_bytes        = p->tx_bytes;
403                 } while (u64_stats_fetch_retry_irq(&p->syncp, start));
404
405                 stats->rx_packets       += rx_packets;
406                 stats->rx_bytes         += rx_bytes;
407                 stats->tx_packets       += tx_packets;
408                 stats->tx_bytes         += tx_bytes;
409                 /* tx_dropped is u32, updated without syncp protection. */
410                 tx_dropped      += p->tx_dropped;
411         }
412         stats->tx_dropped       = tx_dropped;
413         return stats;
414 }
415
416 static int mlxsw_sx_port_get_phys_port_name(struct net_device *dev, char *name,
417                                             size_t len)
418 {
419         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
420         int err;
421
422         err = snprintf(name, len, "p%d", mlxsw_sx_port->mapping.module + 1);
423         if (err >= len)
424                 return -EINVAL;
425
426         return 0;
427 }
428
429 static const struct net_device_ops mlxsw_sx_port_netdev_ops = {
430         .ndo_open               = mlxsw_sx_port_open,
431         .ndo_stop               = mlxsw_sx_port_stop,
432         .ndo_start_xmit         = mlxsw_sx_port_xmit,
433         .ndo_change_mtu         = mlxsw_sx_port_change_mtu,
434         .ndo_get_stats64        = mlxsw_sx_port_get_stats64,
435         .ndo_get_phys_port_name = mlxsw_sx_port_get_phys_port_name,
436 };
437
438 static void mlxsw_sx_port_get_drvinfo(struct net_device *dev,
439                                       struct ethtool_drvinfo *drvinfo)
440 {
441         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
442         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
443
444         strlcpy(drvinfo->driver, mlxsw_sx_driver_name, sizeof(drvinfo->driver));
445         strlcpy(drvinfo->version, mlxsw_sx_driver_version,
446                 sizeof(drvinfo->version));
447         snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
448                  "%d.%d.%d",
449                  mlxsw_sx->bus_info->fw_rev.major,
450                  mlxsw_sx->bus_info->fw_rev.minor,
451                  mlxsw_sx->bus_info->fw_rev.subminor);
452         strlcpy(drvinfo->bus_info, mlxsw_sx->bus_info->device_name,
453                 sizeof(drvinfo->bus_info));
454 }
455
456 struct mlxsw_sx_port_hw_stats {
457         char str[ETH_GSTRING_LEN];
458         u64 (*getter)(const char *payload);
459 };
460
461 static const struct mlxsw_sx_port_hw_stats mlxsw_sx_port_hw_stats[] = {
462         {
463                 .str = "a_frames_transmitted_ok",
464                 .getter = mlxsw_reg_ppcnt_a_frames_transmitted_ok_get,
465         },
466         {
467                 .str = "a_frames_received_ok",
468                 .getter = mlxsw_reg_ppcnt_a_frames_received_ok_get,
469         },
470         {
471                 .str = "a_frame_check_sequence_errors",
472                 .getter = mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get,
473         },
474         {
475                 .str = "a_alignment_errors",
476                 .getter = mlxsw_reg_ppcnt_a_alignment_errors_get,
477         },
478         {
479                 .str = "a_octets_transmitted_ok",
480                 .getter = mlxsw_reg_ppcnt_a_octets_transmitted_ok_get,
481         },
482         {
483                 .str = "a_octets_received_ok",
484                 .getter = mlxsw_reg_ppcnt_a_octets_received_ok_get,
485         },
486         {
487                 .str = "a_multicast_frames_xmitted_ok",
488                 .getter = mlxsw_reg_ppcnt_a_multicast_frames_xmitted_ok_get,
489         },
490         {
491                 .str = "a_broadcast_frames_xmitted_ok",
492                 .getter = mlxsw_reg_ppcnt_a_broadcast_frames_xmitted_ok_get,
493         },
494         {
495                 .str = "a_multicast_frames_received_ok",
496                 .getter = mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get,
497         },
498         {
499                 .str = "a_broadcast_frames_received_ok",
500                 .getter = mlxsw_reg_ppcnt_a_broadcast_frames_received_ok_get,
501         },
502         {
503                 .str = "a_in_range_length_errors",
504                 .getter = mlxsw_reg_ppcnt_a_in_range_length_errors_get,
505         },
506         {
507                 .str = "a_out_of_range_length_field",
508                 .getter = mlxsw_reg_ppcnt_a_out_of_range_length_field_get,
509         },
510         {
511                 .str = "a_frame_too_long_errors",
512                 .getter = mlxsw_reg_ppcnt_a_frame_too_long_errors_get,
513         },
514         {
515                 .str = "a_symbol_error_during_carrier",
516                 .getter = mlxsw_reg_ppcnt_a_symbol_error_during_carrier_get,
517         },
518         {
519                 .str = "a_mac_control_frames_transmitted",
520                 .getter = mlxsw_reg_ppcnt_a_mac_control_frames_transmitted_get,
521         },
522         {
523                 .str = "a_mac_control_frames_received",
524                 .getter = mlxsw_reg_ppcnt_a_mac_control_frames_received_get,
525         },
526         {
527                 .str = "a_unsupported_opcodes_received",
528                 .getter = mlxsw_reg_ppcnt_a_unsupported_opcodes_received_get,
529         },
530         {
531                 .str = "a_pause_mac_ctrl_frames_received",
532                 .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_received_get,
533         },
534         {
535                 .str = "a_pause_mac_ctrl_frames_xmitted",
536                 .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_transmitted_get,
537         },
538 };
539
540 #define MLXSW_SX_PORT_HW_STATS_LEN ARRAY_SIZE(mlxsw_sx_port_hw_stats)
541
542 static void mlxsw_sx_port_get_strings(struct net_device *dev,
543                                       u32 stringset, u8 *data)
544 {
545         u8 *p = data;
546         int i;
547
548         switch (stringset) {
549         case ETH_SS_STATS:
550                 for (i = 0; i < MLXSW_SX_PORT_HW_STATS_LEN; i++) {
551                         memcpy(p, mlxsw_sx_port_hw_stats[i].str,
552                                ETH_GSTRING_LEN);
553                         p += ETH_GSTRING_LEN;
554                 }
555                 break;
556         }
557 }
558
559 static void mlxsw_sx_port_get_stats(struct net_device *dev,
560                                     struct ethtool_stats *stats, u64 *data)
561 {
562         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
563         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
564         char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
565         int i;
566         int err;
567
568         mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sx_port->local_port,
569                              MLXSW_REG_PPCNT_IEEE_8023_CNT, 0);
570         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ppcnt), ppcnt_pl);
571         for (i = 0; i < MLXSW_SX_PORT_HW_STATS_LEN; i++)
572                 data[i] = !err ? mlxsw_sx_port_hw_stats[i].getter(ppcnt_pl) : 0;
573 }
574
575 static int mlxsw_sx_port_get_sset_count(struct net_device *dev, int sset)
576 {
577         switch (sset) {
578         case ETH_SS_STATS:
579                 return MLXSW_SX_PORT_HW_STATS_LEN;
580         default:
581                 return -EOPNOTSUPP;
582         }
583 }
584
585 struct mlxsw_sx_port_link_mode {
586         u32 mask;
587         u32 supported;
588         u32 advertised;
589         u32 speed;
590 };
591
592 static const struct mlxsw_sx_port_link_mode mlxsw_sx_port_link_mode[] = {
593         {
594                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T,
595                 .supported      = SUPPORTED_100baseT_Full,
596                 .advertised     = ADVERTISED_100baseT_Full,
597                 .speed          = 100,
598         },
599         {
600                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100BASE_TX,
601                 .speed          = 100,
602         },
603         {
604                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_SGMII |
605                                   MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX,
606                 .supported      = SUPPORTED_1000baseKX_Full,
607                 .advertised     = ADVERTISED_1000baseKX_Full,
608                 .speed          = 1000,
609         },
610         {
611                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_T,
612                 .supported      = SUPPORTED_10000baseT_Full,
613                 .advertised     = ADVERTISED_10000baseT_Full,
614                 .speed          = 10000,
615         },
616         {
617                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 |
618                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4,
619                 .supported      = SUPPORTED_10000baseKX4_Full,
620                 .advertised     = ADVERTISED_10000baseKX4_Full,
621                 .speed          = 10000,
622         },
623         {
624                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
625                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
626                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
627                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR,
628                 .supported      = SUPPORTED_10000baseKR_Full,
629                 .advertised     = ADVERTISED_10000baseKR_Full,
630                 .speed          = 10000,
631         },
632         {
633                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2,
634                 .supported      = SUPPORTED_20000baseKR2_Full,
635                 .advertised     = ADVERTISED_20000baseKR2_Full,
636                 .speed          = 20000,
637         },
638         {
639                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4,
640                 .supported      = SUPPORTED_40000baseCR4_Full,
641                 .advertised     = ADVERTISED_40000baseCR4_Full,
642                 .speed          = 40000,
643         },
644         {
645                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4,
646                 .supported      = SUPPORTED_40000baseKR4_Full,
647                 .advertised     = ADVERTISED_40000baseKR4_Full,
648                 .speed          = 40000,
649         },
650         {
651                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4,
652                 .supported      = SUPPORTED_40000baseSR4_Full,
653                 .advertised     = ADVERTISED_40000baseSR4_Full,
654                 .speed          = 40000,
655         },
656         {
657                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4,
658                 .supported      = SUPPORTED_40000baseLR4_Full,
659                 .advertised     = ADVERTISED_40000baseLR4_Full,
660                 .speed          = 40000,
661         },
662         {
663                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR |
664                                   MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR |
665                                   MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
666                 .speed          = 25000,
667         },
668         {
669                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR4 |
670                                   MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2 |
671                                   MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
672                 .speed          = 50000,
673         },
674         {
675                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
676                 .supported      = SUPPORTED_56000baseKR4_Full,
677                 .advertised     = ADVERTISED_56000baseKR4_Full,
678                 .speed          = 56000,
679         },
680         {
681                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 |
682                                   MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
683                                   MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
684                                   MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
685                 .speed          = 100000,
686         },
687 };
688
689 #define MLXSW_SX_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sx_port_link_mode)
690 #define MLXSW_SX_PORT_BASE_SPEED 10000 /* Mb/s */
691
692 static u32 mlxsw_sx_from_ptys_supported_port(u32 ptys_eth_proto)
693 {
694         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
695                               MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
696                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 |
697                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 |
698                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
699                               MLXSW_REG_PTYS_ETH_SPEED_SGMII))
700                 return SUPPORTED_FIBRE;
701
702         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
703                               MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 |
704                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 |
705                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
706                               MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX))
707                 return SUPPORTED_Backplane;
708         return 0;
709 }
710
711 static u32 mlxsw_sx_from_ptys_supported_link(u32 ptys_eth_proto)
712 {
713         u32 modes = 0;
714         int i;
715
716         for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
717                 if (ptys_eth_proto & mlxsw_sx_port_link_mode[i].mask)
718                         modes |= mlxsw_sx_port_link_mode[i].supported;
719         }
720         return modes;
721 }
722
723 static u32 mlxsw_sx_from_ptys_advert_link(u32 ptys_eth_proto)
724 {
725         u32 modes = 0;
726         int i;
727
728         for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
729                 if (ptys_eth_proto & mlxsw_sx_port_link_mode[i].mask)
730                         modes |= mlxsw_sx_port_link_mode[i].advertised;
731         }
732         return modes;
733 }
734
735 static void mlxsw_sx_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto,
736                                             struct ethtool_cmd *cmd)
737 {
738         u32 speed = SPEED_UNKNOWN;
739         u8 duplex = DUPLEX_UNKNOWN;
740         int i;
741
742         if (!carrier_ok)
743                 goto out;
744
745         for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
746                 if (ptys_eth_proto & mlxsw_sx_port_link_mode[i].mask) {
747                         speed = mlxsw_sx_port_link_mode[i].speed;
748                         duplex = DUPLEX_FULL;
749                         break;
750                 }
751         }
752 out:
753         ethtool_cmd_speed_set(cmd, speed);
754         cmd->duplex = duplex;
755 }
756
757 static u8 mlxsw_sx_port_connector_port(u32 ptys_eth_proto)
758 {
759         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
760                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 |
761                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
762                               MLXSW_REG_PTYS_ETH_SPEED_SGMII))
763                 return PORT_FIBRE;
764
765         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
766                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 |
767                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4))
768                 return PORT_DA;
769
770         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
771                               MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 |
772                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 |
773                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4))
774                 return PORT_NONE;
775
776         return PORT_OTHER;
777 }
778
779 static int mlxsw_sx_port_get_settings(struct net_device *dev,
780                                       struct ethtool_cmd *cmd)
781 {
782         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
783         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
784         char ptys_pl[MLXSW_REG_PTYS_LEN];
785         u32 eth_proto_cap;
786         u32 eth_proto_admin;
787         u32 eth_proto_oper;
788         int err;
789
790         mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0);
791         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
792         if (err) {
793                 netdev_err(dev, "Failed to get proto");
794                 return err;
795         }
796         mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap,
797                                   &eth_proto_admin, &eth_proto_oper);
798
799         cmd->supported = mlxsw_sx_from_ptys_supported_port(eth_proto_cap) |
800                          mlxsw_sx_from_ptys_supported_link(eth_proto_cap) |
801                          SUPPORTED_Pause | SUPPORTED_Asym_Pause;
802         cmd->advertising = mlxsw_sx_from_ptys_advert_link(eth_proto_admin);
803         mlxsw_sx_from_ptys_speed_duplex(netif_carrier_ok(dev),
804                                         eth_proto_oper, cmd);
805
806         eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
807         cmd->port = mlxsw_sx_port_connector_port(eth_proto_oper);
808         cmd->lp_advertising = mlxsw_sx_from_ptys_advert_link(eth_proto_oper);
809
810         cmd->transceiver = XCVR_INTERNAL;
811         return 0;
812 }
813
814 static u32 mlxsw_sx_to_ptys_advert_link(u32 advertising)
815 {
816         u32 ptys_proto = 0;
817         int i;
818
819         for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
820                 if (advertising & mlxsw_sx_port_link_mode[i].advertised)
821                         ptys_proto |= mlxsw_sx_port_link_mode[i].mask;
822         }
823         return ptys_proto;
824 }
825
826 static u32 mlxsw_sx_to_ptys_speed(u32 speed)
827 {
828         u32 ptys_proto = 0;
829         int i;
830
831         for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
832                 if (speed == mlxsw_sx_port_link_mode[i].speed)
833                         ptys_proto |= mlxsw_sx_port_link_mode[i].mask;
834         }
835         return ptys_proto;
836 }
837
838 static u32 mlxsw_sx_to_ptys_upper_speed(u32 upper_speed)
839 {
840         u32 ptys_proto = 0;
841         int i;
842
843         for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
844                 if (mlxsw_sx_port_link_mode[i].speed <= upper_speed)
845                         ptys_proto |= mlxsw_sx_port_link_mode[i].mask;
846         }
847         return ptys_proto;
848 }
849
850 static int mlxsw_sx_port_set_settings(struct net_device *dev,
851                                       struct ethtool_cmd *cmd)
852 {
853         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
854         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
855         char ptys_pl[MLXSW_REG_PTYS_LEN];
856         u32 speed;
857         u32 eth_proto_new;
858         u32 eth_proto_cap;
859         u32 eth_proto_admin;
860         bool is_up;
861         int err;
862
863         speed = ethtool_cmd_speed(cmd);
864
865         eth_proto_new = cmd->autoneg == AUTONEG_ENABLE ?
866                 mlxsw_sx_to_ptys_advert_link(cmd->advertising) :
867                 mlxsw_sx_to_ptys_speed(speed);
868
869         mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0);
870         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
871         if (err) {
872                 netdev_err(dev, "Failed to get proto");
873                 return err;
874         }
875         mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin,
876                                   NULL);
877
878         eth_proto_new = eth_proto_new & eth_proto_cap;
879         if (!eth_proto_new) {
880                 netdev_err(dev, "Not supported proto admin requested");
881                 return -EINVAL;
882         }
883         if (eth_proto_new == eth_proto_admin)
884                 return 0;
885
886         mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port,
887                                 eth_proto_new);
888         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
889         if (err) {
890                 netdev_err(dev, "Failed to set proto admin");
891                 return err;
892         }
893
894         err = mlxsw_sx_port_oper_status_get(mlxsw_sx_port, &is_up);
895         if (err) {
896                 netdev_err(dev, "Failed to get oper status");
897                 return err;
898         }
899         if (!is_up)
900                 return 0;
901
902         err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false);
903         if (err) {
904                 netdev_err(dev, "Failed to set admin status");
905                 return err;
906         }
907
908         err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, true);
909         if (err) {
910                 netdev_err(dev, "Failed to set admin status");
911                 return err;
912         }
913
914         return 0;
915 }
916
917 static const struct ethtool_ops mlxsw_sx_port_ethtool_ops = {
918         .get_drvinfo            = mlxsw_sx_port_get_drvinfo,
919         .get_link               = ethtool_op_get_link,
920         .get_strings            = mlxsw_sx_port_get_strings,
921         .get_ethtool_stats      = mlxsw_sx_port_get_stats,
922         .get_sset_count         = mlxsw_sx_port_get_sset_count,
923         .get_settings           = mlxsw_sx_port_get_settings,
924         .set_settings           = mlxsw_sx_port_set_settings,
925 };
926
927 static int mlxsw_sx_port_attr_get(struct net_device *dev,
928                                   struct switchdev_attr *attr)
929 {
930         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
931         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
932
933         switch (attr->id) {
934         case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
935                 attr->u.ppid.id_len = sizeof(mlxsw_sx->hw_id);
936                 memcpy(&attr->u.ppid.id, &mlxsw_sx->hw_id, attr->u.ppid.id_len);
937                 break;
938         default:
939                 return -EOPNOTSUPP;
940         }
941
942         return 0;
943 }
944
945 static const struct switchdev_ops mlxsw_sx_port_switchdev_ops = {
946         .switchdev_port_attr_get        = mlxsw_sx_port_attr_get,
947 };
948
949 static int mlxsw_sx_hw_id_get(struct mlxsw_sx *mlxsw_sx)
950 {
951         char spad_pl[MLXSW_REG_SPAD_LEN] = {0};
952         int err;
953
954         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(spad), spad_pl);
955         if (err)
956                 return err;
957         mlxsw_reg_spad_base_mac_memcpy_from(spad_pl, mlxsw_sx->hw_id);
958         return 0;
959 }
960
961 static int mlxsw_sx_port_dev_addr_get(struct mlxsw_sx_port *mlxsw_sx_port)
962 {
963         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
964         struct net_device *dev = mlxsw_sx_port->dev;
965         char ppad_pl[MLXSW_REG_PPAD_LEN];
966         int err;
967
968         mlxsw_reg_ppad_pack(ppad_pl, false, 0);
969         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ppad), ppad_pl);
970         if (err)
971                 return err;
972         mlxsw_reg_ppad_mac_memcpy_from(ppad_pl, dev->dev_addr);
973         /* The last byte value in base mac address is guaranteed
974          * to be such it does not overflow when adding local_port
975          * value.
976          */
977         dev->dev_addr[ETH_ALEN - 1] += mlxsw_sx_port->local_port;
978         return 0;
979 }
980
981 static int mlxsw_sx_port_stp_state_set(struct mlxsw_sx_port *mlxsw_sx_port,
982                                        u16 vid, enum mlxsw_reg_spms_state state)
983 {
984         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
985         char *spms_pl;
986         int err;
987
988         spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL);
989         if (!spms_pl)
990                 return -ENOMEM;
991         mlxsw_reg_spms_pack(spms_pl, mlxsw_sx_port->local_port);
992         mlxsw_reg_spms_vid_pack(spms_pl, vid, state);
993         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spms), spms_pl);
994         kfree(spms_pl);
995         return err;
996 }
997
998 static int mlxsw_sx_port_ib_speed_set(struct mlxsw_sx_port *mlxsw_sx_port,
999                                       u16 speed, u16 width)
1000 {
1001         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
1002         char ptys_pl[MLXSW_REG_PTYS_LEN];
1003
1004         mlxsw_reg_ptys_ib_pack(ptys_pl, mlxsw_sx_port->local_port, speed,
1005                                width);
1006         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
1007 }
1008
1009 static int
1010 mlxsw_sx_port_speed_by_width_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 width)
1011 {
1012         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
1013         u32 upper_speed = MLXSW_SX_PORT_BASE_SPEED * width;
1014         char ptys_pl[MLXSW_REG_PTYS_LEN];
1015         u32 eth_proto_admin;
1016
1017         eth_proto_admin = mlxsw_sx_to_ptys_upper_speed(upper_speed);
1018         mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port,
1019                                 eth_proto_admin);
1020         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
1021 }
1022
1023 static int
1024 mlxsw_sx_port_mac_learning_mode_set(struct mlxsw_sx_port *mlxsw_sx_port,
1025                                     enum mlxsw_reg_spmlr_learn_mode mode)
1026 {
1027         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
1028         char spmlr_pl[MLXSW_REG_SPMLR_LEN];
1029
1030         mlxsw_reg_spmlr_pack(spmlr_pl, mlxsw_sx_port->local_port, mode);
1031         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spmlr), spmlr_pl);
1032 }
1033
1034 static int __mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
1035                                       u8 module, u8 width)
1036 {
1037         struct mlxsw_sx_port *mlxsw_sx_port;
1038         struct net_device *dev;
1039         int err;
1040
1041         dev = alloc_etherdev(sizeof(struct mlxsw_sx_port));
1042         if (!dev)
1043                 return -ENOMEM;
1044         SET_NETDEV_DEV(dev, mlxsw_sx->bus_info->dev);
1045         mlxsw_sx_port = netdev_priv(dev);
1046         mlxsw_sx_port->dev = dev;
1047         mlxsw_sx_port->mlxsw_sx = mlxsw_sx;
1048         mlxsw_sx_port->local_port = local_port;
1049         mlxsw_sx_port->mapping.module = module;
1050
1051         mlxsw_sx_port->pcpu_stats =
1052                 netdev_alloc_pcpu_stats(struct mlxsw_sx_port_pcpu_stats);
1053         if (!mlxsw_sx_port->pcpu_stats) {
1054                 err = -ENOMEM;
1055                 goto err_alloc_stats;
1056         }
1057
1058         dev->netdev_ops = &mlxsw_sx_port_netdev_ops;
1059         dev->ethtool_ops = &mlxsw_sx_port_ethtool_ops;
1060         dev->switchdev_ops = &mlxsw_sx_port_switchdev_ops;
1061
1062         err = mlxsw_sx_port_dev_addr_get(mlxsw_sx_port);
1063         if (err) {
1064                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Unable to get port mac address\n",
1065                         mlxsw_sx_port->local_port);
1066                 goto err_dev_addr_get;
1067         }
1068
1069         netif_carrier_off(dev);
1070
1071         dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_LLTX | NETIF_F_SG |
1072                          NETIF_F_VLAN_CHALLENGED;
1073
1074         dev->min_mtu = 0;
1075         dev->max_mtu = ETH_MAX_MTU;
1076
1077         /* Each packet needs to have a Tx header (metadata) on top all other
1078          * headers.
1079          */
1080         dev->needed_headroom = MLXSW_TXHDR_LEN;
1081
1082         err = mlxsw_sx_port_system_port_mapping_set(mlxsw_sx_port);
1083         if (err) {
1084                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set system port mapping\n",
1085                         mlxsw_sx_port->local_port);
1086                 goto err_port_system_port_mapping_set;
1087         }
1088
1089         err = mlxsw_sx_port_swid_set(mlxsw_sx_port, 0);
1090         if (err) {
1091                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set SWID\n",
1092                         mlxsw_sx_port->local_port);
1093                 goto err_port_swid_set;
1094         }
1095
1096         err = mlxsw_sx_port_speed_by_width_set(mlxsw_sx_port, width);
1097         if (err) {
1098                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set speed\n",
1099                         mlxsw_sx_port->local_port);
1100                 goto err_port_speed_set;
1101         }
1102
1103         err = mlxsw_sx_port_mtu_eth_set(mlxsw_sx_port, ETH_DATA_LEN);
1104         if (err) {
1105                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MTU\n",
1106                         mlxsw_sx_port->local_port);
1107                 goto err_port_mtu_set;
1108         }
1109
1110         err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false);
1111         if (err)
1112                 goto err_port_admin_status_set;
1113
1114         err = mlxsw_sx_port_stp_state_set(mlxsw_sx_port,
1115                                           MLXSW_PORT_DEFAULT_VID,
1116                                           MLXSW_REG_SPMS_STATE_FORWARDING);
1117         if (err) {
1118                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set STP state\n",
1119                         mlxsw_sx_port->local_port);
1120                 goto err_port_stp_state_set;
1121         }
1122
1123         err = mlxsw_sx_port_mac_learning_mode_set(mlxsw_sx_port,
1124                                                   MLXSW_REG_SPMLR_LEARN_MODE_DISABLE);
1125         if (err) {
1126                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MAC learning mode\n",
1127                         mlxsw_sx_port->local_port);
1128                 goto err_port_mac_learning_mode_set;
1129         }
1130
1131         err = register_netdev(dev);
1132         if (err) {
1133                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to register netdev\n",
1134                         mlxsw_sx_port->local_port);
1135                 goto err_register_netdev;
1136         }
1137
1138         mlxsw_core_port_eth_set(mlxsw_sx->core, mlxsw_sx_port->local_port,
1139                                 mlxsw_sx_port, dev, false, 0);
1140         mlxsw_sx->ports[local_port] = mlxsw_sx_port;
1141         return 0;
1142
1143 err_register_netdev:
1144 err_port_mac_learning_mode_set:
1145 err_port_stp_state_set:
1146 err_port_admin_status_set:
1147 err_port_mtu_set:
1148 err_port_speed_set:
1149         mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
1150 err_port_swid_set:
1151 err_port_system_port_mapping_set:
1152 err_dev_addr_get:
1153         free_percpu(mlxsw_sx_port->pcpu_stats);
1154 err_alloc_stats:
1155         free_netdev(dev);
1156         return err;
1157 }
1158
1159 static int mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
1160                                     u8 module, u8 width)
1161 {
1162         int err;
1163
1164         err = mlxsw_core_port_init(mlxsw_sx->core, local_port);
1165         if (err) {
1166                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to init core port\n",
1167                         local_port);
1168                 return err;
1169         }
1170         err = __mlxsw_sx_port_eth_create(mlxsw_sx, local_port, module, width);
1171         if (err)
1172                 goto err_port_create;
1173
1174         return 0;
1175
1176 err_port_create:
1177         mlxsw_core_port_fini(mlxsw_sx->core, local_port);
1178         return err;
1179 }
1180
1181 static void __mlxsw_sx_port_eth_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
1182 {
1183         struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port];
1184
1185         mlxsw_core_port_clear(mlxsw_sx->core, local_port, mlxsw_sx);
1186         unregister_netdev(mlxsw_sx_port->dev); /* This calls ndo_stop */
1187         mlxsw_sx->ports[local_port] = NULL;
1188         mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
1189         free_percpu(mlxsw_sx_port->pcpu_stats);
1190         free_netdev(mlxsw_sx_port->dev);
1191 }
1192
1193 static bool mlxsw_sx_port_created(struct mlxsw_sx *mlxsw_sx, u8 local_port)
1194 {
1195         return mlxsw_sx->ports[local_port] != NULL;
1196 }
1197
1198 static int __mlxsw_sx_port_ib_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
1199                                      u8 module, u8 width)
1200 {
1201         struct mlxsw_sx_port *mlxsw_sx_port;
1202         int err;
1203
1204         mlxsw_sx_port = kzalloc(sizeof(*mlxsw_sx_port), GFP_KERNEL);
1205         if (!mlxsw_sx_port)
1206                 return -ENOMEM;
1207         mlxsw_sx_port->mlxsw_sx = mlxsw_sx;
1208         mlxsw_sx_port->local_port = local_port;
1209         mlxsw_sx_port->mapping.module = module;
1210
1211         err = mlxsw_sx_port_system_port_mapping_set(mlxsw_sx_port);
1212         if (err) {
1213                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set system port mapping\n",
1214                         mlxsw_sx_port->local_port);
1215                 goto err_port_system_port_mapping_set;
1216         }
1217
1218         /* Adding port to Infiniband swid (1) */
1219         err = mlxsw_sx_port_swid_set(mlxsw_sx_port, 1);
1220         if (err) {
1221                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set SWID\n",
1222                         mlxsw_sx_port->local_port);
1223                 goto err_port_swid_set;
1224         }
1225
1226         /* Expose the IB port number as it's front panel name */
1227         err = mlxsw_sx_port_ib_port_set(mlxsw_sx_port, module + 1);
1228         if (err) {
1229                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set IB port\n",
1230                         mlxsw_sx_port->local_port);
1231                 goto err_port_ib_set;
1232         }
1233
1234         /* Supports all speeds from SDR to FDR (bitmask) and support bus width
1235          * of 1x, 2x and 4x (3 bits bitmask)
1236          */
1237         err = mlxsw_sx_port_ib_speed_set(mlxsw_sx_port,
1238                                          MLXSW_REG_PTYS_IB_SPEED_EDR - 1,
1239                                          BIT(3) - 1);
1240         if (err) {
1241                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set speed\n",
1242                         mlxsw_sx_port->local_port);
1243                 goto err_port_speed_set;
1244         }
1245
1246         /* Change to the maximum MTU the device supports, the SMA will take
1247          * care of the active MTU
1248          */
1249         err = mlxsw_sx_port_mtu_ib_set(mlxsw_sx_port, MLXSW_IB_DEFAULT_MTU);
1250         if (err) {
1251                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MTU\n",
1252                         mlxsw_sx_port->local_port);
1253                 goto err_port_mtu_set;
1254         }
1255
1256         err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, true);
1257         if (err) {
1258                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to change admin state to UP\n",
1259                         mlxsw_sx_port->local_port);
1260                 goto err_port_admin_set;
1261         }
1262
1263         mlxsw_core_port_ib_set(mlxsw_sx->core, mlxsw_sx_port->local_port,
1264                                mlxsw_sx_port);
1265         mlxsw_sx->ports[local_port] = mlxsw_sx_port;
1266         return 0;
1267
1268 err_port_admin_set:
1269 err_port_mtu_set:
1270 err_port_speed_set:
1271 err_port_ib_set:
1272         mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
1273 err_port_swid_set:
1274 err_port_system_port_mapping_set:
1275         kfree(mlxsw_sx_port);
1276         return err;
1277 }
1278
1279 static void __mlxsw_sx_port_ib_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
1280 {
1281         struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port];
1282
1283         mlxsw_core_port_clear(mlxsw_sx->core, local_port, mlxsw_sx);
1284         mlxsw_sx->ports[local_port] = NULL;
1285         mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false);
1286         mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
1287         kfree(mlxsw_sx_port);
1288 }
1289
1290 static void __mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
1291 {
1292         enum devlink_port_type port_type =
1293                 mlxsw_core_port_type_get(mlxsw_sx->core, local_port);
1294
1295         if (port_type == DEVLINK_PORT_TYPE_ETH)
1296                 __mlxsw_sx_port_eth_remove(mlxsw_sx, local_port);
1297         else if (port_type == DEVLINK_PORT_TYPE_IB)
1298                 __mlxsw_sx_port_ib_remove(mlxsw_sx, local_port);
1299 }
1300
1301 static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
1302 {
1303         __mlxsw_sx_port_remove(mlxsw_sx, local_port);
1304         mlxsw_core_port_fini(mlxsw_sx->core, local_port);
1305 }
1306
1307 static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx)
1308 {
1309         int i;
1310
1311         for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++)
1312                 if (mlxsw_sx_port_created(mlxsw_sx, i))
1313                         mlxsw_sx_port_remove(mlxsw_sx, i);
1314         kfree(mlxsw_sx->ports);
1315 }
1316
1317 static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx)
1318 {
1319         size_t alloc_size;
1320         u8 module, width;
1321         int i;
1322         int err;
1323
1324         alloc_size = sizeof(struct mlxsw_sx_port *) * MLXSW_PORT_MAX_PORTS;
1325         mlxsw_sx->ports = kzalloc(alloc_size, GFP_KERNEL);
1326         if (!mlxsw_sx->ports)
1327                 return -ENOMEM;
1328
1329         for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) {
1330                 err = mlxsw_sx_port_module_info_get(mlxsw_sx, i, &module,
1331                                                     &width);
1332                 if (err)
1333                         goto err_port_module_info_get;
1334                 if (!width)
1335                         continue;
1336                 err = mlxsw_sx_port_eth_create(mlxsw_sx, i, module, width);
1337                 if (err)
1338                         goto err_port_create;
1339         }
1340         return 0;
1341
1342 err_port_create:
1343 err_port_module_info_get:
1344         for (i--; i >= 1; i--)
1345                 if (mlxsw_sx_port_created(mlxsw_sx, i))
1346                         mlxsw_sx_port_remove(mlxsw_sx, i);
1347         kfree(mlxsw_sx->ports);
1348         return err;
1349 }
1350
1351 static void mlxsw_sx_pude_eth_event_func(struct mlxsw_sx_port *mlxsw_sx_port,
1352                                          enum mlxsw_reg_pude_oper_status status)
1353 {
1354         if (status == MLXSW_PORT_OPER_STATUS_UP) {
1355                 netdev_info(mlxsw_sx_port->dev, "link up\n");
1356                 netif_carrier_on(mlxsw_sx_port->dev);
1357         } else {
1358                 netdev_info(mlxsw_sx_port->dev, "link down\n");
1359                 netif_carrier_off(mlxsw_sx_port->dev);
1360         }
1361 }
1362
1363 static void mlxsw_sx_pude_ib_event_func(struct mlxsw_sx_port *mlxsw_sx_port,
1364                                         enum mlxsw_reg_pude_oper_status status)
1365 {
1366         if (status == MLXSW_PORT_OPER_STATUS_UP)
1367                 pr_info("ib link for port %d - up\n",
1368                         mlxsw_sx_port->mapping.module + 1);
1369         else
1370                 pr_info("ib link for port %d - down\n",
1371                         mlxsw_sx_port->mapping.module + 1);
1372 }
1373
1374 static void mlxsw_sx_pude_event_func(const struct mlxsw_reg_info *reg,
1375                                      char *pude_pl, void *priv)
1376 {
1377         struct mlxsw_sx *mlxsw_sx = priv;
1378         struct mlxsw_sx_port *mlxsw_sx_port;
1379         enum mlxsw_reg_pude_oper_status status;
1380         enum devlink_port_type port_type;
1381         u8 local_port;
1382
1383         local_port = mlxsw_reg_pude_local_port_get(pude_pl);
1384         mlxsw_sx_port = mlxsw_sx->ports[local_port];
1385         if (!mlxsw_sx_port) {
1386                 dev_warn(mlxsw_sx->bus_info->dev, "Port %d: Link event received for non-existent port\n",
1387                          local_port);
1388                 return;
1389         }
1390
1391         status = mlxsw_reg_pude_oper_status_get(pude_pl);
1392         port_type = mlxsw_core_port_type_get(mlxsw_sx->core, local_port);
1393         if (port_type == DEVLINK_PORT_TYPE_ETH)
1394                 mlxsw_sx_pude_eth_event_func(mlxsw_sx_port, status);
1395         else if (port_type == DEVLINK_PORT_TYPE_IB)
1396                 mlxsw_sx_pude_ib_event_func(mlxsw_sx_port, status);
1397 }
1398
1399 static void mlxsw_sx_rx_listener_func(struct sk_buff *skb, u8 local_port,
1400                                       void *priv)
1401 {
1402         struct mlxsw_sx *mlxsw_sx = priv;
1403         struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port];
1404         struct mlxsw_sx_port_pcpu_stats *pcpu_stats;
1405
1406         if (unlikely(!mlxsw_sx_port)) {
1407                 dev_warn_ratelimited(mlxsw_sx->bus_info->dev, "Port %d: skb received for non-existent port\n",
1408                                      local_port);
1409                 return;
1410         }
1411
1412         skb->dev = mlxsw_sx_port->dev;
1413
1414         pcpu_stats = this_cpu_ptr(mlxsw_sx_port->pcpu_stats);
1415         u64_stats_update_begin(&pcpu_stats->syncp);
1416         pcpu_stats->rx_packets++;
1417         pcpu_stats->rx_bytes += skb->len;
1418         u64_stats_update_end(&pcpu_stats->syncp);
1419
1420         skb->protocol = eth_type_trans(skb, skb->dev);
1421         netif_receive_skb(skb);
1422 }
1423
1424 static int mlxsw_sx_port_type_set(struct mlxsw_core *mlxsw_core, u8 local_port,
1425                                   enum devlink_port_type new_type)
1426 {
1427         struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core);
1428         u8 module, width;
1429         int err;
1430
1431         if (new_type == DEVLINK_PORT_TYPE_AUTO)
1432                 return -EOPNOTSUPP;
1433
1434         __mlxsw_sx_port_remove(mlxsw_sx, local_port);
1435         err = mlxsw_sx_port_module_info_get(mlxsw_sx, local_port, &module,
1436                                             &width);
1437         if (err)
1438                 goto err_port_module_info_get;
1439
1440         if (new_type == DEVLINK_PORT_TYPE_ETH)
1441                 err = __mlxsw_sx_port_eth_create(mlxsw_sx, local_port, module,
1442                                                  width);
1443         else if (new_type == DEVLINK_PORT_TYPE_IB)
1444                 err = __mlxsw_sx_port_ib_create(mlxsw_sx, local_port, module,
1445                                                 width);
1446
1447 err_port_module_info_get:
1448         return err;
1449 }
1450
1451 #define MLXSW_SX_RXL(_trap_id) \
1452         MLXSW_RXL(mlxsw_sx_rx_listener_func, _trap_id, TRAP_TO_CPU,     \
1453                   false, SX2_RX, FORWARD)
1454
1455 static const struct mlxsw_listener mlxsw_sx_listener[] = {
1456         MLXSW_EVENTL(mlxsw_sx_pude_event_func, PUDE, EMAD),
1457         MLXSW_SX_RXL(FDB_MC),
1458         MLXSW_SX_RXL(STP),
1459         MLXSW_SX_RXL(LACP),
1460         MLXSW_SX_RXL(EAPOL),
1461         MLXSW_SX_RXL(LLDP),
1462         MLXSW_SX_RXL(MMRP),
1463         MLXSW_SX_RXL(MVRP),
1464         MLXSW_SX_RXL(RPVST),
1465         MLXSW_SX_RXL(DHCP),
1466         MLXSW_SX_RXL(IGMP_QUERY),
1467         MLXSW_SX_RXL(IGMP_V1_REPORT),
1468         MLXSW_SX_RXL(IGMP_V2_REPORT),
1469         MLXSW_SX_RXL(IGMP_V2_LEAVE),
1470         MLXSW_SX_RXL(IGMP_V3_REPORT),
1471 };
1472
1473 static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx)
1474 {
1475         char htgt_pl[MLXSW_REG_HTGT_LEN];
1476         int i;
1477         int err;
1478
1479         mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_SX2_RX,
1480                             MLXSW_REG_HTGT_INVALID_POLICER,
1481                             MLXSW_REG_HTGT_DEFAULT_PRIORITY,
1482                             MLXSW_REG_HTGT_DEFAULT_TC);
1483         mlxsw_reg_htgt_local_path_rdq_set(htgt_pl,
1484                                           MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_RX);
1485
1486         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(htgt), htgt_pl);
1487         if (err)
1488                 return err;
1489
1490         mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_SX2_CTRL,
1491                             MLXSW_REG_HTGT_INVALID_POLICER,
1492                             MLXSW_REG_HTGT_DEFAULT_PRIORITY,
1493                             MLXSW_REG_HTGT_DEFAULT_TC);
1494         mlxsw_reg_htgt_local_path_rdq_set(htgt_pl,
1495                                         MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_CTRL);
1496
1497         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(htgt), htgt_pl);
1498         if (err)
1499                 return err;
1500
1501         for (i = 0; i < ARRAY_SIZE(mlxsw_sx_listener); i++) {
1502                 err = mlxsw_core_trap_register(mlxsw_sx->core,
1503                                                &mlxsw_sx_listener[i],
1504                                                mlxsw_sx);
1505                 if (err)
1506                         goto err_listener_register;
1507
1508         }
1509         return 0;
1510
1511 err_listener_register:
1512         for (i--; i >= 0; i--) {
1513                 mlxsw_core_trap_unregister(mlxsw_sx->core,
1514                                            &mlxsw_sx_listener[i],
1515                                            mlxsw_sx);
1516         }
1517         return err;
1518 }
1519
1520 static void mlxsw_sx_traps_fini(struct mlxsw_sx *mlxsw_sx)
1521 {
1522         int i;
1523
1524         for (i = 0; i < ARRAY_SIZE(mlxsw_sx_listener); i++) {
1525                 mlxsw_core_trap_unregister(mlxsw_sx->core,
1526                                            &mlxsw_sx_listener[i],
1527                                            mlxsw_sx);
1528         }
1529 }
1530
1531 static int mlxsw_sx_flood_init(struct mlxsw_sx *mlxsw_sx)
1532 {
1533         char sfgc_pl[MLXSW_REG_SFGC_LEN];
1534         char sgcr_pl[MLXSW_REG_SGCR_LEN];
1535         char *sftr_pl;
1536         int err;
1537
1538         /* Configure a flooding table, which includes only CPU port. */
1539         sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
1540         if (!sftr_pl)
1541                 return -ENOMEM;
1542         mlxsw_reg_sftr_pack(sftr_pl, 0, 0, MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 0,
1543                             MLXSW_PORT_CPU_PORT, true);
1544         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sftr), sftr_pl);
1545         kfree(sftr_pl);
1546         if (err)
1547                 return err;
1548
1549         /* Flood different packet types using the flooding table. */
1550         mlxsw_reg_sfgc_pack(sfgc_pl,
1551                             MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST,
1552                             MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
1553                             MLXSW_REG_SFGC_TABLE_TYPE_SINGLE,
1554                             0);
1555         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl);
1556         if (err)
1557                 return err;
1558
1559         mlxsw_reg_sfgc_pack(sfgc_pl,
1560                             MLXSW_REG_SFGC_TYPE_BROADCAST,
1561                             MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
1562                             MLXSW_REG_SFGC_TABLE_TYPE_SINGLE,
1563                             0);
1564         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl);
1565         if (err)
1566                 return err;
1567
1568         mlxsw_reg_sfgc_pack(sfgc_pl,
1569                             MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP,
1570                             MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
1571                             MLXSW_REG_SFGC_TABLE_TYPE_SINGLE,
1572                             0);
1573         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl);
1574         if (err)
1575                 return err;
1576
1577         mlxsw_reg_sfgc_pack(sfgc_pl,
1578                             MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6,
1579                             MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
1580                             MLXSW_REG_SFGC_TABLE_TYPE_SINGLE,
1581                             0);
1582         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl);
1583         if (err)
1584                 return err;
1585
1586         mlxsw_reg_sfgc_pack(sfgc_pl,
1587                             MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4,
1588                             MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
1589                             MLXSW_REG_SFGC_TABLE_TYPE_SINGLE,
1590                             0);
1591         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl);
1592         if (err)
1593                 return err;
1594
1595         mlxsw_reg_sgcr_pack(sgcr_pl, true);
1596         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sgcr), sgcr_pl);
1597 }
1598
1599 static int mlxsw_sx_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
1600 {
1601         char htgt_pl[MLXSW_REG_HTGT_LEN];
1602
1603         mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
1604                             MLXSW_REG_HTGT_INVALID_POLICER,
1605                             MLXSW_REG_HTGT_DEFAULT_PRIORITY,
1606                             MLXSW_REG_HTGT_DEFAULT_TC);
1607         mlxsw_reg_htgt_swid_set(htgt_pl, MLXSW_PORT_SWID_ALL_SWIDS);
1608         mlxsw_reg_htgt_local_path_rdq_set(htgt_pl,
1609                                         MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_EMAD);
1610         return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
1611 }
1612
1613 static int mlxsw_sx_init(struct mlxsw_core *mlxsw_core,
1614                          const struct mlxsw_bus_info *mlxsw_bus_info)
1615 {
1616         struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core);
1617         int err;
1618
1619         mlxsw_sx->core = mlxsw_core;
1620         mlxsw_sx->bus_info = mlxsw_bus_info;
1621
1622         err = mlxsw_sx_hw_id_get(mlxsw_sx);
1623         if (err) {
1624                 dev_err(mlxsw_sx->bus_info->dev, "Failed to get switch HW ID\n");
1625                 return err;
1626         }
1627
1628         err = mlxsw_sx_ports_create(mlxsw_sx);
1629         if (err) {
1630                 dev_err(mlxsw_sx->bus_info->dev, "Failed to create ports\n");
1631                 return err;
1632         }
1633
1634         err = mlxsw_sx_traps_init(mlxsw_sx);
1635         if (err) {
1636                 dev_err(mlxsw_sx->bus_info->dev, "Failed to set traps\n");
1637                 goto err_listener_register;
1638         }
1639
1640         err = mlxsw_sx_flood_init(mlxsw_sx);
1641         if (err) {
1642                 dev_err(mlxsw_sx->bus_info->dev, "Failed to initialize flood tables\n");
1643                 goto err_flood_init;
1644         }
1645
1646         return 0;
1647
1648 err_flood_init:
1649         mlxsw_sx_traps_fini(mlxsw_sx);
1650 err_listener_register:
1651         mlxsw_sx_ports_remove(mlxsw_sx);
1652         return err;
1653 }
1654
1655 static void mlxsw_sx_fini(struct mlxsw_core *mlxsw_core)
1656 {
1657         struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core);
1658
1659         mlxsw_sx_traps_fini(mlxsw_sx);
1660         mlxsw_sx_ports_remove(mlxsw_sx);
1661 }
1662
1663 static struct mlxsw_config_profile mlxsw_sx_config_profile = {
1664         .used_max_vepa_channels         = 1,
1665         .max_vepa_channels              = 0,
1666         .used_max_mid                   = 1,
1667         .max_mid                        = 7000,
1668         .used_max_pgt                   = 1,
1669         .max_pgt                        = 0,
1670         .used_max_system_port           = 1,
1671         .max_system_port                = 48000,
1672         .used_max_vlan_groups           = 1,
1673         .max_vlan_groups                = 127,
1674         .used_max_regions               = 1,
1675         .max_regions                    = 400,
1676         .used_flood_tables              = 1,
1677         .max_flood_tables               = 2,
1678         .max_vid_flood_tables           = 1,
1679         .used_flood_mode                = 1,
1680         .flood_mode                     = 3,
1681         .used_max_ib_mc                 = 1,
1682         .max_ib_mc                      = 6,
1683         .used_max_pkey                  = 1,
1684         .max_pkey                       = 0,
1685         .swid_config                    = {
1686                 {
1687                         .used_type      = 1,
1688                         .type           = MLXSW_PORT_SWID_TYPE_ETH,
1689                 },
1690                 {
1691                         .used_type      = 1,
1692                         .type           = MLXSW_PORT_SWID_TYPE_IB,
1693                 }
1694         },
1695         .resource_query_enable          = 0,
1696 };
1697
1698 static struct mlxsw_driver mlxsw_sx_driver = {
1699         .kind                   = mlxsw_sx_driver_name,
1700         .priv_size              = sizeof(struct mlxsw_sx),
1701         .init                   = mlxsw_sx_init,
1702         .fini                   = mlxsw_sx_fini,
1703         .basic_trap_groups_set  = mlxsw_sx_basic_trap_groups_set,
1704         .txhdr_construct        = mlxsw_sx_txhdr_construct,
1705         .txhdr_len              = MLXSW_TXHDR_LEN,
1706         .profile                = &mlxsw_sx_config_profile,
1707         .port_type_set          = mlxsw_sx_port_type_set,
1708 };
1709
1710 static const struct pci_device_id mlxsw_sx_pci_id_table[] = {
1711         {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHX2), 0},
1712         {0, },
1713 };
1714
1715 static struct pci_driver mlxsw_sx_pci_driver = {
1716         .name = mlxsw_sx_driver_name,
1717         .id_table = mlxsw_sx_pci_id_table,
1718 };
1719
1720 static int __init mlxsw_sx_module_init(void)
1721 {
1722         int err;
1723
1724         err = mlxsw_core_driver_register(&mlxsw_sx_driver);
1725         if (err)
1726                 return err;
1727
1728         err = mlxsw_pci_driver_register(&mlxsw_sx_pci_driver);
1729         if (err)
1730                 goto err_pci_driver_register;
1731
1732         return 0;
1733
1734 err_pci_driver_register:
1735         mlxsw_core_driver_unregister(&mlxsw_sx_driver);
1736         return err;
1737 }
1738
1739 static void __exit mlxsw_sx_module_exit(void)
1740 {
1741         mlxsw_pci_driver_unregister(&mlxsw_sx_pci_driver);
1742         mlxsw_core_driver_unregister(&mlxsw_sx_driver);
1743 }
1744
1745 module_init(mlxsw_sx_module_init);
1746 module_exit(mlxsw_sx_module_exit);
1747
1748 MODULE_LICENSE("Dual BSD/GPL");
1749 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
1750 MODULE_DESCRIPTION("Mellanox SwitchX-2 driver");
1751 MODULE_DEVICE_TABLE(pci, mlxsw_sx_pci_id_table);