]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/ethernet/mellanox/mlxsw/switchx2.c
Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdim...
[karo-tx-linux.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 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/netdevice.h>
41 #include <linux/etherdevice.h>
42 #include <linux/slab.h>
43 #include <linux/device.h>
44 #include <linux/skbuff.h>
45 #include <linux/if_vlan.h>
46 #include <net/switchdev.h>
47 #include <generated/utsrelease.h>
48
49 #include "core.h"
50 #include "reg.h"
51 #include "port.h"
52 #include "trap.h"
53 #include "txheader.h"
54
55 static const char mlxsw_sx_driver_name[] = "mlxsw_switchx2";
56 static const char mlxsw_sx_driver_version[] = "1.0";
57
58 struct mlxsw_sx_port;
59
60 #define MLXSW_SW_HW_ID_LEN 6
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[MLXSW_SW_HW_ID_LEN];
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 };
84
85 /* tx_hdr_version
86  * Tx header version.
87  * Must be set to 0.
88  */
89 MLXSW_ITEM32(tx, hdr, version, 0x00, 28, 4);
90
91 /* tx_hdr_ctl
92  * Packet control type.
93  * 0 - Ethernet control (e.g. EMADs, LACP)
94  * 1 - Ethernet data
95  */
96 MLXSW_ITEM32(tx, hdr, ctl, 0x00, 26, 2);
97
98 /* tx_hdr_proto
99  * Packet protocol type. Must be set to 1 (Ethernet).
100  */
101 MLXSW_ITEM32(tx, hdr, proto, 0x00, 21, 3);
102
103 /* tx_hdr_etclass
104  * Egress TClass to be used on the egress device on the egress port.
105  * The MSB is specified in the 'ctclass3' field.
106  * Range is 0-15, where 15 is the highest priority.
107  */
108 MLXSW_ITEM32(tx, hdr, etclass, 0x00, 18, 3);
109
110 /* tx_hdr_swid
111  * Switch partition ID.
112  */
113 MLXSW_ITEM32(tx, hdr, swid, 0x00, 12, 3);
114
115 /* tx_hdr_port_mid
116  * Destination local port for unicast packets.
117  * Destination multicast ID for multicast packets.
118  *
119  * Control packets are directed to a specific egress port, while data
120  * packets are transmitted through the CPU port (0) into the switch partition,
121  * where forwarding rules are applied.
122  */
123 MLXSW_ITEM32(tx, hdr, port_mid, 0x04, 16, 16);
124
125 /* tx_hdr_ctclass3
126  * See field 'etclass'.
127  */
128 MLXSW_ITEM32(tx, hdr, ctclass3, 0x04, 14, 1);
129
130 /* tx_hdr_rdq
131  * RDQ for control packets sent to remote CPU.
132  * Must be set to 0x1F for EMADs, otherwise 0.
133  */
134 MLXSW_ITEM32(tx, hdr, rdq, 0x04, 9, 5);
135
136 /* tx_hdr_cpu_sig
137  * Signature control for packets going to CPU. Must be set to 0.
138  */
139 MLXSW_ITEM32(tx, hdr, cpu_sig, 0x04, 0, 9);
140
141 /* tx_hdr_sig
142  * Stacking protocl signature. Must be set to 0xE0E0.
143  */
144 MLXSW_ITEM32(tx, hdr, sig, 0x0C, 16, 16);
145
146 /* tx_hdr_stclass
147  * Stacking TClass.
148  */
149 MLXSW_ITEM32(tx, hdr, stclass, 0x0C, 13, 3);
150
151 /* tx_hdr_emad
152  * EMAD bit. Must be set for EMADs.
153  */
154 MLXSW_ITEM32(tx, hdr, emad, 0x0C, 5, 1);
155
156 /* tx_hdr_type
157  * 0 - Data packets
158  * 6 - Control packets
159  */
160 MLXSW_ITEM32(tx, hdr, type, 0x0C, 0, 4);
161
162 static void mlxsw_sx_txhdr_construct(struct sk_buff *skb,
163                                      const struct mlxsw_tx_info *tx_info)
164 {
165         char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN);
166         bool is_emad = tx_info->is_emad;
167
168         memset(txhdr, 0, MLXSW_TXHDR_LEN);
169
170         /* We currently set default values for the egress tclass (QoS). */
171         mlxsw_tx_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_0);
172         mlxsw_tx_hdr_ctl_set(txhdr, MLXSW_TXHDR_ETH_CTL);
173         mlxsw_tx_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH);
174         mlxsw_tx_hdr_etclass_set(txhdr, is_emad ? MLXSW_TXHDR_ETCLASS_6 :
175                                                   MLXSW_TXHDR_ETCLASS_5);
176         mlxsw_tx_hdr_swid_set(txhdr, 0);
177         mlxsw_tx_hdr_port_mid_set(txhdr, tx_info->local_port);
178         mlxsw_tx_hdr_ctclass3_set(txhdr, MLXSW_TXHDR_CTCLASS3);
179         mlxsw_tx_hdr_rdq_set(txhdr, is_emad ? MLXSW_TXHDR_RDQ_EMAD :
180                                               MLXSW_TXHDR_RDQ_OTHER);
181         mlxsw_tx_hdr_cpu_sig_set(txhdr, MLXSW_TXHDR_CPU_SIG);
182         mlxsw_tx_hdr_sig_set(txhdr, MLXSW_TXHDR_SIG);
183         mlxsw_tx_hdr_stclass_set(txhdr, MLXSW_TXHDR_STCLASS_NONE);
184         mlxsw_tx_hdr_emad_set(txhdr, is_emad ? MLXSW_TXHDR_EMAD :
185                                                MLXSW_TXHDR_NOT_EMAD);
186         mlxsw_tx_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL);
187 }
188
189 static int mlxsw_sx_port_admin_status_set(struct mlxsw_sx_port *mlxsw_sx_port,
190                                           bool is_up)
191 {
192         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
193         char paos_pl[MLXSW_REG_PAOS_LEN];
194
195         mlxsw_reg_paos_pack(paos_pl, mlxsw_sx_port->local_port,
196                             is_up ? MLXSW_PORT_ADMIN_STATUS_UP :
197                             MLXSW_PORT_ADMIN_STATUS_DOWN);
198         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(paos), paos_pl);
199 }
200
201 static int mlxsw_sx_port_oper_status_get(struct mlxsw_sx_port *mlxsw_sx_port,
202                                          bool *p_is_up)
203 {
204         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
205         char paos_pl[MLXSW_REG_PAOS_LEN];
206         u8 oper_status;
207         int err;
208
209         mlxsw_reg_paos_pack(paos_pl, mlxsw_sx_port->local_port, 0);
210         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(paos), paos_pl);
211         if (err)
212                 return err;
213         oper_status = mlxsw_reg_paos_oper_status_get(paos_pl);
214         *p_is_up = oper_status == MLXSW_PORT_ADMIN_STATUS_UP ? true : false;
215         return 0;
216 }
217
218 static int mlxsw_sx_port_mtu_set(struct mlxsw_sx_port *mlxsw_sx_port, u16 mtu)
219 {
220         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
221         char pmtu_pl[MLXSW_REG_PMTU_LEN];
222         int max_mtu;
223         int err;
224
225         mtu += MLXSW_TXHDR_LEN + ETH_HLEN;
226         mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sx_port->local_port, 0);
227         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmtu), pmtu_pl);
228         if (err)
229                 return err;
230         max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl);
231
232         if (mtu > max_mtu)
233                 return -EINVAL;
234
235         mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sx_port->local_port, mtu);
236         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(pmtu), pmtu_pl);
237 }
238
239 static int mlxsw_sx_port_swid_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 swid)
240 {
241         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
242         char pspa_pl[MLXSW_REG_PSPA_LEN];
243
244         mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sx_port->local_port);
245         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(pspa), pspa_pl);
246 }
247
248 static int
249 mlxsw_sx_port_system_port_mapping_set(struct mlxsw_sx_port *mlxsw_sx_port)
250 {
251         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
252         char sspr_pl[MLXSW_REG_SSPR_LEN];
253
254         mlxsw_reg_sspr_pack(sspr_pl, mlxsw_sx_port->local_port);
255         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sspr), sspr_pl);
256 }
257
258 static int mlxsw_sx_port_module_check(struct mlxsw_sx_port *mlxsw_sx_port,
259                                       bool *p_usable)
260 {
261         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
262         char pmlp_pl[MLXSW_REG_PMLP_LEN];
263         int err;
264
265         mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sx_port->local_port);
266         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(pmlp), pmlp_pl);
267         if (err)
268                 return err;
269         *p_usable = mlxsw_reg_pmlp_width_get(pmlp_pl) ? true : false;
270         return 0;
271 }
272
273 static int mlxsw_sx_port_open(struct net_device *dev)
274 {
275         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
276         int err;
277
278         err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, true);
279         if (err)
280                 return err;
281         netif_start_queue(dev);
282         return 0;
283 }
284
285 static int mlxsw_sx_port_stop(struct net_device *dev)
286 {
287         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
288
289         netif_stop_queue(dev);
290         return mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false);
291 }
292
293 static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb,
294                                       struct net_device *dev)
295 {
296         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
297         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
298         struct mlxsw_sx_port_pcpu_stats *pcpu_stats;
299         const struct mlxsw_tx_info tx_info = {
300                 .local_port = mlxsw_sx_port->local_port,
301                 .is_emad = false,
302         };
303         u64 len;
304         int err;
305
306         if (mlxsw_core_skb_transmit_busy(mlxsw_sx, &tx_info))
307                 return NETDEV_TX_BUSY;
308
309         if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) {
310                 struct sk_buff *skb_orig = skb;
311
312                 skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN);
313                 if (!skb) {
314                         this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped);
315                         dev_kfree_skb_any(skb_orig);
316                         return NETDEV_TX_OK;
317                 }
318         }
319         mlxsw_sx_txhdr_construct(skb, &tx_info);
320         len = skb->len;
321         /* Due to a race we might fail here because of a full queue. In that
322          * unlikely case we simply drop the packet.
323          */
324         err = mlxsw_core_skb_transmit(mlxsw_sx, skb, &tx_info);
325
326         if (!err) {
327                 pcpu_stats = this_cpu_ptr(mlxsw_sx_port->pcpu_stats);
328                 u64_stats_update_begin(&pcpu_stats->syncp);
329                 pcpu_stats->tx_packets++;
330                 pcpu_stats->tx_bytes += len;
331                 u64_stats_update_end(&pcpu_stats->syncp);
332         } else {
333                 this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped);
334                 dev_kfree_skb_any(skb);
335         }
336         return NETDEV_TX_OK;
337 }
338
339 static int mlxsw_sx_port_change_mtu(struct net_device *dev, int mtu)
340 {
341         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
342         int err;
343
344         err = mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu);
345         if (err)
346                 return err;
347         dev->mtu = mtu;
348         return 0;
349 }
350
351 static struct rtnl_link_stats64 *
352 mlxsw_sx_port_get_stats64(struct net_device *dev,
353                           struct rtnl_link_stats64 *stats)
354 {
355         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
356         struct mlxsw_sx_port_pcpu_stats *p;
357         u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
358         u32 tx_dropped = 0;
359         unsigned int start;
360         int i;
361
362         for_each_possible_cpu(i) {
363                 p = per_cpu_ptr(mlxsw_sx_port->pcpu_stats, i);
364                 do {
365                         start = u64_stats_fetch_begin_irq(&p->syncp);
366                         rx_packets      = p->rx_packets;
367                         rx_bytes        = p->rx_bytes;
368                         tx_packets      = p->tx_packets;
369                         tx_bytes        = p->tx_bytes;
370                 } while (u64_stats_fetch_retry_irq(&p->syncp, start));
371
372                 stats->rx_packets       += rx_packets;
373                 stats->rx_bytes         += rx_bytes;
374                 stats->tx_packets       += tx_packets;
375                 stats->tx_bytes         += tx_bytes;
376                 /* tx_dropped is u32, updated without syncp protection. */
377                 tx_dropped      += p->tx_dropped;
378         }
379         stats->tx_dropped       = tx_dropped;
380         return stats;
381 }
382
383 static const struct net_device_ops mlxsw_sx_port_netdev_ops = {
384         .ndo_open               = mlxsw_sx_port_open,
385         .ndo_stop               = mlxsw_sx_port_stop,
386         .ndo_start_xmit         = mlxsw_sx_port_xmit,
387         .ndo_change_mtu         = mlxsw_sx_port_change_mtu,
388         .ndo_get_stats64        = mlxsw_sx_port_get_stats64,
389 };
390
391 static void mlxsw_sx_port_get_drvinfo(struct net_device *dev,
392                                       struct ethtool_drvinfo *drvinfo)
393 {
394         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
395         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
396
397         strlcpy(drvinfo->driver, mlxsw_sx_driver_name, sizeof(drvinfo->driver));
398         strlcpy(drvinfo->version, mlxsw_sx_driver_version,
399                 sizeof(drvinfo->version));
400         snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
401                  "%d.%d.%d",
402                  mlxsw_sx->bus_info->fw_rev.major,
403                  mlxsw_sx->bus_info->fw_rev.minor,
404                  mlxsw_sx->bus_info->fw_rev.subminor);
405         strlcpy(drvinfo->bus_info, mlxsw_sx->bus_info->device_name,
406                 sizeof(drvinfo->bus_info));
407 }
408
409 struct mlxsw_sx_port_hw_stats {
410         char str[ETH_GSTRING_LEN];
411         u64 (*getter)(char *payload);
412 };
413
414 static const struct mlxsw_sx_port_hw_stats mlxsw_sx_port_hw_stats[] = {
415         {
416                 .str = "a_frames_transmitted_ok",
417                 .getter = mlxsw_reg_ppcnt_a_frames_transmitted_ok_get,
418         },
419         {
420                 .str = "a_frames_received_ok",
421                 .getter = mlxsw_reg_ppcnt_a_frames_received_ok_get,
422         },
423         {
424                 .str = "a_frame_check_sequence_errors",
425                 .getter = mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get,
426         },
427         {
428                 .str = "a_alignment_errors",
429                 .getter = mlxsw_reg_ppcnt_a_alignment_errors_get,
430         },
431         {
432                 .str = "a_octets_transmitted_ok",
433                 .getter = mlxsw_reg_ppcnt_a_octets_transmitted_ok_get,
434         },
435         {
436                 .str = "a_octets_received_ok",
437                 .getter = mlxsw_reg_ppcnt_a_octets_received_ok_get,
438         },
439         {
440                 .str = "a_multicast_frames_xmitted_ok",
441                 .getter = mlxsw_reg_ppcnt_a_multicast_frames_xmitted_ok_get,
442         },
443         {
444                 .str = "a_broadcast_frames_xmitted_ok",
445                 .getter = mlxsw_reg_ppcnt_a_broadcast_frames_xmitted_ok_get,
446         },
447         {
448                 .str = "a_multicast_frames_received_ok",
449                 .getter = mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get,
450         },
451         {
452                 .str = "a_broadcast_frames_received_ok",
453                 .getter = mlxsw_reg_ppcnt_a_broadcast_frames_received_ok_get,
454         },
455         {
456                 .str = "a_in_range_length_errors",
457                 .getter = mlxsw_reg_ppcnt_a_in_range_length_errors_get,
458         },
459         {
460                 .str = "a_out_of_range_length_field",
461                 .getter = mlxsw_reg_ppcnt_a_out_of_range_length_field_get,
462         },
463         {
464                 .str = "a_frame_too_long_errors",
465                 .getter = mlxsw_reg_ppcnt_a_frame_too_long_errors_get,
466         },
467         {
468                 .str = "a_symbol_error_during_carrier",
469                 .getter = mlxsw_reg_ppcnt_a_symbol_error_during_carrier_get,
470         },
471         {
472                 .str = "a_mac_control_frames_transmitted",
473                 .getter = mlxsw_reg_ppcnt_a_mac_control_frames_transmitted_get,
474         },
475         {
476                 .str = "a_mac_control_frames_received",
477                 .getter = mlxsw_reg_ppcnt_a_mac_control_frames_received_get,
478         },
479         {
480                 .str = "a_unsupported_opcodes_received",
481                 .getter = mlxsw_reg_ppcnt_a_unsupported_opcodes_received_get,
482         },
483         {
484                 .str = "a_pause_mac_ctrl_frames_received",
485                 .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_received_get,
486         },
487         {
488                 .str = "a_pause_mac_ctrl_frames_xmitted",
489                 .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_transmitted_get,
490         },
491 };
492
493 #define MLXSW_SX_PORT_HW_STATS_LEN ARRAY_SIZE(mlxsw_sx_port_hw_stats)
494
495 static void mlxsw_sx_port_get_strings(struct net_device *dev,
496                                       u32 stringset, u8 *data)
497 {
498         u8 *p = data;
499         int i;
500
501         switch (stringset) {
502         case ETH_SS_STATS:
503                 for (i = 0; i < MLXSW_SX_PORT_HW_STATS_LEN; i++) {
504                         memcpy(p, mlxsw_sx_port_hw_stats[i].str,
505                                ETH_GSTRING_LEN);
506                         p += ETH_GSTRING_LEN;
507                 }
508                 break;
509         }
510 }
511
512 static void mlxsw_sx_port_get_stats(struct net_device *dev,
513                                     struct ethtool_stats *stats, u64 *data)
514 {
515         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
516         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
517         char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
518         int i;
519         int err;
520
521         mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sx_port->local_port);
522         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ppcnt), ppcnt_pl);
523         for (i = 0; i < MLXSW_SX_PORT_HW_STATS_LEN; i++)
524                 data[i] = !err ? mlxsw_sx_port_hw_stats[i].getter(ppcnt_pl) : 0;
525 }
526
527 static int mlxsw_sx_port_get_sset_count(struct net_device *dev, int sset)
528 {
529         switch (sset) {
530         case ETH_SS_STATS:
531                 return MLXSW_SX_PORT_HW_STATS_LEN;
532         default:
533                 return -EOPNOTSUPP;
534         }
535 }
536
537 struct mlxsw_sx_port_link_mode {
538         u32 mask;
539         u32 supported;
540         u32 advertised;
541         u32 speed;
542 };
543
544 static const struct mlxsw_sx_port_link_mode mlxsw_sx_port_link_mode[] = {
545         {
546                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T,
547                 .supported      = SUPPORTED_100baseT_Full,
548                 .advertised     = ADVERTISED_100baseT_Full,
549                 .speed          = 100,
550         },
551         {
552                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100BASE_TX,
553                 .speed          = 100,
554         },
555         {
556                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_SGMII |
557                                   MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX,
558                 .supported      = SUPPORTED_1000baseKX_Full,
559                 .advertised     = ADVERTISED_1000baseKX_Full,
560                 .speed          = 1000,
561         },
562         {
563                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_T,
564                 .supported      = SUPPORTED_10000baseT_Full,
565                 .advertised     = ADVERTISED_10000baseT_Full,
566                 .speed          = 10000,
567         },
568         {
569                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 |
570                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4,
571                 .supported      = SUPPORTED_10000baseKX4_Full,
572                 .advertised     = ADVERTISED_10000baseKX4_Full,
573                 .speed          = 10000,
574         },
575         {
576                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
577                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
578                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
579                                   MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR,
580                 .supported      = SUPPORTED_10000baseKR_Full,
581                 .advertised     = ADVERTISED_10000baseKR_Full,
582                 .speed          = 10000,
583         },
584         {
585                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2,
586                 .supported      = SUPPORTED_20000baseKR2_Full,
587                 .advertised     = ADVERTISED_20000baseKR2_Full,
588                 .speed          = 20000,
589         },
590         {
591                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4,
592                 .supported      = SUPPORTED_40000baseCR4_Full,
593                 .advertised     = ADVERTISED_40000baseCR4_Full,
594                 .speed          = 40000,
595         },
596         {
597                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4,
598                 .supported      = SUPPORTED_40000baseKR4_Full,
599                 .advertised     = ADVERTISED_40000baseKR4_Full,
600                 .speed          = 40000,
601         },
602         {
603                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4,
604                 .supported      = SUPPORTED_40000baseSR4_Full,
605                 .advertised     = ADVERTISED_40000baseSR4_Full,
606                 .speed          = 40000,
607         },
608         {
609                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4,
610                 .supported      = SUPPORTED_40000baseLR4_Full,
611                 .advertised     = ADVERTISED_40000baseLR4_Full,
612                 .speed          = 40000,
613         },
614         {
615                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR |
616                                   MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR |
617                                   MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
618                 .speed          = 25000,
619         },
620         {
621                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR4 |
622                                   MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2 |
623                                   MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
624                 .speed          = 50000,
625         },
626         {
627                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
628                 .supported      = SUPPORTED_56000baseKR4_Full,
629                 .advertised     = ADVERTISED_56000baseKR4_Full,
630                 .speed          = 56000,
631         },
632         {
633                 .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 |
634                                   MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
635                                   MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
636                                   MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
637                 .speed          = 100000,
638         },
639 };
640
641 #define MLXSW_SX_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sx_port_link_mode)
642
643 static u32 mlxsw_sx_from_ptys_supported_port(u32 ptys_eth_proto)
644 {
645         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
646                               MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
647                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 |
648                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 |
649                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
650                               MLXSW_REG_PTYS_ETH_SPEED_SGMII))
651                 return SUPPORTED_FIBRE;
652
653         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
654                               MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 |
655                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 |
656                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
657                               MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX))
658                 return SUPPORTED_Backplane;
659         return 0;
660 }
661
662 static u32 mlxsw_sx_from_ptys_supported_link(u32 ptys_eth_proto)
663 {
664         u32 modes = 0;
665         int i;
666
667         for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
668                 if (ptys_eth_proto & mlxsw_sx_port_link_mode[i].mask)
669                         modes |= mlxsw_sx_port_link_mode[i].supported;
670         }
671         return modes;
672 }
673
674 static u32 mlxsw_sx_from_ptys_advert_link(u32 ptys_eth_proto)
675 {
676         u32 modes = 0;
677         int i;
678
679         for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
680                 if (ptys_eth_proto & mlxsw_sx_port_link_mode[i].mask)
681                         modes |= mlxsw_sx_port_link_mode[i].advertised;
682         }
683         return modes;
684 }
685
686 static void mlxsw_sx_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto,
687                                             struct ethtool_cmd *cmd)
688 {
689         u32 speed = SPEED_UNKNOWN;
690         u8 duplex = DUPLEX_UNKNOWN;
691         int i;
692
693         if (!carrier_ok)
694                 goto out;
695
696         for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
697                 if (ptys_eth_proto & mlxsw_sx_port_link_mode[i].mask) {
698                         speed = mlxsw_sx_port_link_mode[i].speed;
699                         duplex = DUPLEX_FULL;
700                         break;
701                 }
702         }
703 out:
704         ethtool_cmd_speed_set(cmd, speed);
705         cmd->duplex = duplex;
706 }
707
708 static u8 mlxsw_sx_port_connector_port(u32 ptys_eth_proto)
709 {
710         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
711                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 |
712                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
713                               MLXSW_REG_PTYS_ETH_SPEED_SGMII))
714                 return PORT_FIBRE;
715
716         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
717                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 |
718                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4))
719                 return PORT_DA;
720
721         if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
722                               MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 |
723                               MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 |
724                               MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4))
725                 return PORT_NONE;
726
727         return PORT_OTHER;
728 }
729
730 static int mlxsw_sx_port_get_settings(struct net_device *dev,
731                                       struct ethtool_cmd *cmd)
732 {
733         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
734         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
735         char ptys_pl[MLXSW_REG_PTYS_LEN];
736         u32 eth_proto_cap;
737         u32 eth_proto_admin;
738         u32 eth_proto_oper;
739         int err;
740
741         mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, 0);
742         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
743         if (err) {
744                 netdev_err(dev, "Failed to get proto");
745                 return err;
746         }
747         mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap,
748                               &eth_proto_admin, &eth_proto_oper);
749
750         cmd->supported = mlxsw_sx_from_ptys_supported_port(eth_proto_cap) |
751                          mlxsw_sx_from_ptys_supported_link(eth_proto_cap) |
752                          SUPPORTED_Pause | SUPPORTED_Asym_Pause;
753         cmd->advertising = mlxsw_sx_from_ptys_advert_link(eth_proto_admin);
754         mlxsw_sx_from_ptys_speed_duplex(netif_carrier_ok(dev),
755                                         eth_proto_oper, cmd);
756
757         eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
758         cmd->port = mlxsw_sx_port_connector_port(eth_proto_oper);
759         cmd->lp_advertising = mlxsw_sx_from_ptys_advert_link(eth_proto_oper);
760
761         cmd->transceiver = XCVR_INTERNAL;
762         return 0;
763 }
764
765 static u32 mlxsw_sx_to_ptys_advert_link(u32 advertising)
766 {
767         u32 ptys_proto = 0;
768         int i;
769
770         for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
771                 if (advertising & mlxsw_sx_port_link_mode[i].advertised)
772                         ptys_proto |= mlxsw_sx_port_link_mode[i].mask;
773         }
774         return ptys_proto;
775 }
776
777 static u32 mlxsw_sx_to_ptys_speed(u32 speed)
778 {
779         u32 ptys_proto = 0;
780         int i;
781
782         for (i = 0; i < MLXSW_SX_PORT_LINK_MODE_LEN; i++) {
783                 if (speed == mlxsw_sx_port_link_mode[i].speed)
784                         ptys_proto |= mlxsw_sx_port_link_mode[i].mask;
785         }
786         return ptys_proto;
787 }
788
789 static int mlxsw_sx_port_set_settings(struct net_device *dev,
790                                       struct ethtool_cmd *cmd)
791 {
792         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
793         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
794         char ptys_pl[MLXSW_REG_PTYS_LEN];
795         u32 speed;
796         u32 eth_proto_new;
797         u32 eth_proto_cap;
798         u32 eth_proto_admin;
799         bool is_up;
800         int err;
801
802         speed = ethtool_cmd_speed(cmd);
803
804         eth_proto_new = cmd->autoneg == AUTONEG_ENABLE ?
805                 mlxsw_sx_to_ptys_advert_link(cmd->advertising) :
806                 mlxsw_sx_to_ptys_speed(speed);
807
808         mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, 0);
809         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
810         if (err) {
811                 netdev_err(dev, "Failed to get proto");
812                 return err;
813         }
814         mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin, NULL);
815
816         eth_proto_new = eth_proto_new & eth_proto_cap;
817         if (!eth_proto_new) {
818                 netdev_err(dev, "Not supported proto admin requested");
819                 return -EINVAL;
820         }
821         if (eth_proto_new == eth_proto_admin)
822                 return 0;
823
824         mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, eth_proto_new);
825         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
826         if (err) {
827                 netdev_err(dev, "Failed to set proto admin");
828                 return err;
829         }
830
831         err = mlxsw_sx_port_oper_status_get(mlxsw_sx_port, &is_up);
832         if (err) {
833                 netdev_err(dev, "Failed to get oper status");
834                 return err;
835         }
836         if (!is_up)
837                 return 0;
838
839         err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false);
840         if (err) {
841                 netdev_err(dev, "Failed to set admin status");
842                 return err;
843         }
844
845         err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, true);
846         if (err) {
847                 netdev_err(dev, "Failed to set admin status");
848                 return err;
849         }
850
851         return 0;
852 }
853
854 static const struct ethtool_ops mlxsw_sx_port_ethtool_ops = {
855         .get_drvinfo            = mlxsw_sx_port_get_drvinfo,
856         .get_link               = ethtool_op_get_link,
857         .get_strings            = mlxsw_sx_port_get_strings,
858         .get_ethtool_stats      = mlxsw_sx_port_get_stats,
859         .get_sset_count         = mlxsw_sx_port_get_sset_count,
860         .get_settings           = mlxsw_sx_port_get_settings,
861         .set_settings           = mlxsw_sx_port_set_settings,
862 };
863
864 static int mlxsw_sx_port_attr_get(struct net_device *dev,
865                                   struct switchdev_attr *attr)
866 {
867         struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
868         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
869
870         switch (attr->id) {
871         case SWITCHDEV_ATTR_PORT_PARENT_ID:
872                 attr->u.ppid.id_len = sizeof(mlxsw_sx->hw_id);
873                 memcpy(&attr->u.ppid.id, &mlxsw_sx->hw_id, attr->u.ppid.id_len);
874                 break;
875         default:
876                 return -EOPNOTSUPP;
877         }
878
879         return 0;
880 }
881
882 static const struct switchdev_ops mlxsw_sx_port_switchdev_ops = {
883         .switchdev_port_attr_get        = mlxsw_sx_port_attr_get,
884 };
885
886 static int mlxsw_sx_hw_id_get(struct mlxsw_sx *mlxsw_sx)
887 {
888         char spad_pl[MLXSW_REG_SPAD_LEN];
889         int err;
890
891         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(spad), spad_pl);
892         if (err)
893                 return err;
894         mlxsw_reg_spad_base_mac_memcpy_from(spad_pl, mlxsw_sx->hw_id);
895         return 0;
896 }
897
898 static int mlxsw_sx_port_dev_addr_get(struct mlxsw_sx_port *mlxsw_sx_port)
899 {
900         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
901         struct net_device *dev = mlxsw_sx_port->dev;
902         char ppad_pl[MLXSW_REG_PPAD_LEN];
903         int err;
904
905         mlxsw_reg_ppad_pack(ppad_pl, false, 0);
906         err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ppad), ppad_pl);
907         if (err)
908                 return err;
909         mlxsw_reg_ppad_mac_memcpy_from(ppad_pl, dev->dev_addr);
910         /* The last byte value in base mac address is guaranteed
911          * to be such it does not overflow when adding local_port
912          * value.
913          */
914         dev->dev_addr[ETH_ALEN - 1] += mlxsw_sx_port->local_port;
915         return 0;
916 }
917
918 static int mlxsw_sx_port_stp_state_set(struct mlxsw_sx_port *mlxsw_sx_port,
919                                        u16 vid, enum mlxsw_reg_spms_state state)
920 {
921         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
922         char *spms_pl;
923         int err;
924
925         spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL);
926         if (!spms_pl)
927                 return -ENOMEM;
928         mlxsw_reg_spms_pack(spms_pl, mlxsw_sx_port->local_port, vid, state);
929         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spms), spms_pl);
930         kfree(spms_pl);
931         return err;
932 }
933
934 static int mlxsw_sx_port_speed_set(struct mlxsw_sx_port *mlxsw_sx_port,
935                                    u32 speed)
936 {
937         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
938         char ptys_pl[MLXSW_REG_PTYS_LEN];
939
940         mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sx_port->local_port, speed);
941         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
942 }
943
944 static int
945 mlxsw_sx_port_mac_learning_mode_set(struct mlxsw_sx_port *mlxsw_sx_port,
946                                     enum mlxsw_reg_spmlr_learn_mode mode)
947 {
948         struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx;
949         char spmlr_pl[MLXSW_REG_SPMLR_LEN];
950
951         mlxsw_reg_spmlr_pack(spmlr_pl, mlxsw_sx_port->local_port, mode);
952         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spmlr), spmlr_pl);
953 }
954
955 static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
956 {
957         struct mlxsw_sx_port *mlxsw_sx_port;
958         struct net_device *dev;
959         bool usable;
960         int err;
961
962         dev = alloc_etherdev(sizeof(struct mlxsw_sx_port));
963         if (!dev)
964                 return -ENOMEM;
965         mlxsw_sx_port = netdev_priv(dev);
966         mlxsw_sx_port->dev = dev;
967         mlxsw_sx_port->mlxsw_sx = mlxsw_sx;
968         mlxsw_sx_port->local_port = local_port;
969
970         mlxsw_sx_port->pcpu_stats =
971                 netdev_alloc_pcpu_stats(struct mlxsw_sx_port_pcpu_stats);
972         if (!mlxsw_sx_port->pcpu_stats) {
973                 err = -ENOMEM;
974                 goto err_alloc_stats;
975         }
976
977         dev->netdev_ops = &mlxsw_sx_port_netdev_ops;
978         dev->ethtool_ops = &mlxsw_sx_port_ethtool_ops;
979         dev->switchdev_ops = &mlxsw_sx_port_switchdev_ops;
980
981         err = mlxsw_sx_port_dev_addr_get(mlxsw_sx_port);
982         if (err) {
983                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Unable to get port mac address\n",
984                         mlxsw_sx_port->local_port);
985                 goto err_dev_addr_get;
986         }
987
988         netif_carrier_off(dev);
989
990         dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_LLTX | NETIF_F_SG |
991                          NETIF_F_VLAN_CHALLENGED;
992
993         /* Each packet needs to have a Tx header (metadata) on top all other
994          * headers.
995          */
996         dev->hard_header_len += MLXSW_TXHDR_LEN;
997
998         err = mlxsw_sx_port_module_check(mlxsw_sx_port, &usable);
999         if (err) {
1000                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to check module\n",
1001                         mlxsw_sx_port->local_port);
1002                 goto err_port_module_check;
1003         }
1004
1005         if (!usable) {
1006                 dev_dbg(mlxsw_sx->bus_info->dev, "Port %d: Not usable, skipping initialization\n",
1007                         mlxsw_sx_port->local_port);
1008                 goto port_not_usable;
1009         }
1010
1011         err = mlxsw_sx_port_system_port_mapping_set(mlxsw_sx_port);
1012         if (err) {
1013                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set system port mapping\n",
1014                         mlxsw_sx_port->local_port);
1015                 goto err_port_system_port_mapping_set;
1016         }
1017
1018         err = mlxsw_sx_port_swid_set(mlxsw_sx_port, 0);
1019         if (err) {
1020                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set SWID\n",
1021                         mlxsw_sx_port->local_port);
1022                 goto err_port_swid_set;
1023         }
1024
1025         err = mlxsw_sx_port_speed_set(mlxsw_sx_port,
1026                                       MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4);
1027         if (err) {
1028                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set speed\n",
1029                         mlxsw_sx_port->local_port);
1030                 goto err_port_speed_set;
1031         }
1032
1033         err = mlxsw_sx_port_mtu_set(mlxsw_sx_port, ETH_DATA_LEN);
1034         if (err) {
1035                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MTU\n",
1036                         mlxsw_sx_port->local_port);
1037                 goto err_port_mtu_set;
1038         }
1039
1040         err = mlxsw_sx_port_admin_status_set(mlxsw_sx_port, false);
1041         if (err)
1042                 goto err_port_admin_status_set;
1043
1044         err = mlxsw_sx_port_stp_state_set(mlxsw_sx_port,
1045                                           MLXSW_PORT_DEFAULT_VID,
1046                                           MLXSW_REG_SPMS_STATE_FORWARDING);
1047         if (err) {
1048                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set STP state\n",
1049                         mlxsw_sx_port->local_port);
1050                 goto err_port_stp_state_set;
1051         }
1052
1053         err = mlxsw_sx_port_mac_learning_mode_set(mlxsw_sx_port,
1054                                                   MLXSW_REG_SPMLR_LEARN_MODE_DISABLE);
1055         if (err) {
1056                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set MAC learning mode\n",
1057                         mlxsw_sx_port->local_port);
1058                 goto err_port_mac_learning_mode_set;
1059         }
1060
1061         err = register_netdev(dev);
1062         if (err) {
1063                 dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to register netdev\n",
1064                         mlxsw_sx_port->local_port);
1065                 goto err_register_netdev;
1066         }
1067
1068         mlxsw_sx->ports[local_port] = mlxsw_sx_port;
1069         return 0;
1070
1071 err_register_netdev:
1072 err_port_mac_learning_mode_set:
1073 err_port_stp_state_set:
1074 err_port_admin_status_set:
1075 err_port_mtu_set:
1076 err_port_speed_set:
1077 err_port_swid_set:
1078 err_port_system_port_mapping_set:
1079 port_not_usable:
1080 err_port_module_check:
1081 err_dev_addr_get:
1082         free_percpu(mlxsw_sx_port->pcpu_stats);
1083 err_alloc_stats:
1084         free_netdev(dev);
1085         return err;
1086 }
1087
1088 static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
1089 {
1090         struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port];
1091
1092         if (!mlxsw_sx_port)
1093                 return;
1094         unregister_netdev(mlxsw_sx_port->dev); /* This calls ndo_stop */
1095         mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
1096         free_percpu(mlxsw_sx_port->pcpu_stats);
1097         free_netdev(mlxsw_sx_port->dev);
1098 }
1099
1100 static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx)
1101 {
1102         int i;
1103
1104         for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++)
1105                 mlxsw_sx_port_remove(mlxsw_sx, i);
1106         kfree(mlxsw_sx->ports);
1107 }
1108
1109 static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx)
1110 {
1111         size_t alloc_size;
1112         int i;
1113         int err;
1114
1115         alloc_size = sizeof(struct mlxsw_sx_port *) * MLXSW_PORT_MAX_PORTS;
1116         mlxsw_sx->ports = kzalloc(alloc_size, GFP_KERNEL);
1117         if (!mlxsw_sx->ports)
1118                 return -ENOMEM;
1119
1120         for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) {
1121                 err = mlxsw_sx_port_create(mlxsw_sx, i);
1122                 if (err)
1123                         goto err_port_create;
1124         }
1125         return 0;
1126
1127 err_port_create:
1128         for (i--; i >= 1; i--)
1129                 mlxsw_sx_port_remove(mlxsw_sx, i);
1130         kfree(mlxsw_sx->ports);
1131         return err;
1132 }
1133
1134 static void mlxsw_sx_pude_event_func(const struct mlxsw_reg_info *reg,
1135                                      char *pude_pl, void *priv)
1136 {
1137         struct mlxsw_sx *mlxsw_sx = priv;
1138         struct mlxsw_sx_port *mlxsw_sx_port;
1139         enum mlxsw_reg_pude_oper_status status;
1140         u8 local_port;
1141
1142         local_port = mlxsw_reg_pude_local_port_get(pude_pl);
1143         mlxsw_sx_port = mlxsw_sx->ports[local_port];
1144         if (!mlxsw_sx_port) {
1145                 dev_warn(mlxsw_sx->bus_info->dev, "Port %d: Link event received for non-existent port\n",
1146                          local_port);
1147                 return;
1148         }
1149
1150         status = mlxsw_reg_pude_oper_status_get(pude_pl);
1151         if (MLXSW_PORT_OPER_STATUS_UP == status) {
1152                 netdev_info(mlxsw_sx_port->dev, "link up\n");
1153                 netif_carrier_on(mlxsw_sx_port->dev);
1154         } else {
1155                 netdev_info(mlxsw_sx_port->dev, "link down\n");
1156                 netif_carrier_off(mlxsw_sx_port->dev);
1157         }
1158 }
1159
1160 static struct mlxsw_event_listener mlxsw_sx_pude_event = {
1161         .func = mlxsw_sx_pude_event_func,
1162         .trap_id = MLXSW_TRAP_ID_PUDE,
1163 };
1164
1165 static int mlxsw_sx_event_register(struct mlxsw_sx *mlxsw_sx,
1166                                    enum mlxsw_event_trap_id trap_id)
1167 {
1168         struct mlxsw_event_listener *el;
1169         char hpkt_pl[MLXSW_REG_HPKT_LEN];
1170         int err;
1171
1172         switch (trap_id) {
1173         case MLXSW_TRAP_ID_PUDE:
1174                 el = &mlxsw_sx_pude_event;
1175                 break;
1176         }
1177         err = mlxsw_core_event_listener_register(mlxsw_sx->core, el, mlxsw_sx);
1178         if (err)
1179                 return err;
1180
1181         mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD,
1182                             MLXSW_REG_HTGT_TRAP_GROUP_EMAD, trap_id);
1183         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl);
1184         if (err)
1185                 goto err_event_trap_set;
1186
1187         return 0;
1188
1189 err_event_trap_set:
1190         mlxsw_core_event_listener_unregister(mlxsw_sx->core, el, mlxsw_sx);
1191         return err;
1192 }
1193
1194 static void mlxsw_sx_event_unregister(struct mlxsw_sx *mlxsw_sx,
1195                                       enum mlxsw_event_trap_id trap_id)
1196 {
1197         struct mlxsw_event_listener *el;
1198
1199         switch (trap_id) {
1200         case MLXSW_TRAP_ID_PUDE:
1201                 el = &mlxsw_sx_pude_event;
1202                 break;
1203         }
1204         mlxsw_core_event_listener_unregister(mlxsw_sx->core, el, mlxsw_sx);
1205 }
1206
1207 static void mlxsw_sx_rx_listener_func(struct sk_buff *skb, u8 local_port,
1208                                       void *priv)
1209 {
1210         struct mlxsw_sx *mlxsw_sx = priv;
1211         struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port];
1212         struct mlxsw_sx_port_pcpu_stats *pcpu_stats;
1213
1214         if (unlikely(!mlxsw_sx_port)) {
1215                 if (net_ratelimit())
1216                         dev_warn(mlxsw_sx->bus_info->dev, "Port %d: skb received for non-existent port\n",
1217                                  local_port);
1218                 return;
1219         }
1220
1221         skb->dev = mlxsw_sx_port->dev;
1222
1223         pcpu_stats = this_cpu_ptr(mlxsw_sx_port->pcpu_stats);
1224         u64_stats_update_begin(&pcpu_stats->syncp);
1225         pcpu_stats->rx_packets++;
1226         pcpu_stats->rx_bytes += skb->len;
1227         u64_stats_update_end(&pcpu_stats->syncp);
1228
1229         skb->protocol = eth_type_trans(skb, skb->dev);
1230         netif_receive_skb(skb);
1231 }
1232
1233 static const struct mlxsw_rx_listener mlxsw_sx_rx_listener[] = {
1234         {
1235                 .func = mlxsw_sx_rx_listener_func,
1236                 .local_port = MLXSW_PORT_DONT_CARE,
1237                 .trap_id = MLXSW_TRAP_ID_FDB_MC,
1238         },
1239         /* Traps for specific L2 packet types, not trapped as FDB MC */
1240         {
1241                 .func = mlxsw_sx_rx_listener_func,
1242                 .local_port = MLXSW_PORT_DONT_CARE,
1243                 .trap_id = MLXSW_TRAP_ID_STP,
1244         },
1245         {
1246                 .func = mlxsw_sx_rx_listener_func,
1247                 .local_port = MLXSW_PORT_DONT_CARE,
1248                 .trap_id = MLXSW_TRAP_ID_LACP,
1249         },
1250         {
1251                 .func = mlxsw_sx_rx_listener_func,
1252                 .local_port = MLXSW_PORT_DONT_CARE,
1253                 .trap_id = MLXSW_TRAP_ID_EAPOL,
1254         },
1255         {
1256                 .func = mlxsw_sx_rx_listener_func,
1257                 .local_port = MLXSW_PORT_DONT_CARE,
1258                 .trap_id = MLXSW_TRAP_ID_LLDP,
1259         },
1260         {
1261                 .func = mlxsw_sx_rx_listener_func,
1262                 .local_port = MLXSW_PORT_DONT_CARE,
1263                 .trap_id = MLXSW_TRAP_ID_MMRP,
1264         },
1265         {
1266                 .func = mlxsw_sx_rx_listener_func,
1267                 .local_port = MLXSW_PORT_DONT_CARE,
1268                 .trap_id = MLXSW_TRAP_ID_MVRP,
1269         },
1270         {
1271                 .func = mlxsw_sx_rx_listener_func,
1272                 .local_port = MLXSW_PORT_DONT_CARE,
1273                 .trap_id = MLXSW_TRAP_ID_RPVST,
1274         },
1275         {
1276                 .func = mlxsw_sx_rx_listener_func,
1277                 .local_port = MLXSW_PORT_DONT_CARE,
1278                 .trap_id = MLXSW_TRAP_ID_DHCP,
1279         },
1280         {
1281                 .func = mlxsw_sx_rx_listener_func,
1282                 .local_port = MLXSW_PORT_DONT_CARE,
1283                 .trap_id = MLXSW_TRAP_ID_IGMP_QUERY,
1284         },
1285         {
1286                 .func = mlxsw_sx_rx_listener_func,
1287                 .local_port = MLXSW_PORT_DONT_CARE,
1288                 .trap_id = MLXSW_TRAP_ID_IGMP_V1_REPORT,
1289         },
1290         {
1291                 .func = mlxsw_sx_rx_listener_func,
1292                 .local_port = MLXSW_PORT_DONT_CARE,
1293                 .trap_id = MLXSW_TRAP_ID_IGMP_V2_REPORT,
1294         },
1295         {
1296                 .func = mlxsw_sx_rx_listener_func,
1297                 .local_port = MLXSW_PORT_DONT_CARE,
1298                 .trap_id = MLXSW_TRAP_ID_IGMP_V2_LEAVE,
1299         },
1300         {
1301                 .func = mlxsw_sx_rx_listener_func,
1302                 .local_port = MLXSW_PORT_DONT_CARE,
1303                 .trap_id = MLXSW_TRAP_ID_IGMP_V3_REPORT,
1304         },
1305 };
1306
1307 static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx)
1308 {
1309         char htgt_pl[MLXSW_REG_HTGT_LEN];
1310         char hpkt_pl[MLXSW_REG_HPKT_LEN];
1311         int i;
1312         int err;
1313
1314         mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_RX);
1315         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(htgt), htgt_pl);
1316         if (err)
1317                 return err;
1318
1319         for (i = 0; i < ARRAY_SIZE(mlxsw_sx_rx_listener); i++) {
1320                 err = mlxsw_core_rx_listener_register(mlxsw_sx->core,
1321                                                       &mlxsw_sx_rx_listener[i],
1322                                                       mlxsw_sx);
1323                 if (err)
1324                         goto err_rx_listener_register;
1325
1326                 mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU,
1327                                     MLXSW_REG_HTGT_TRAP_GROUP_RX,
1328                                     mlxsw_sx_rx_listener[i].trap_id);
1329                 err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl);
1330                 if (err)
1331                         goto err_rx_trap_set;
1332         }
1333         return 0;
1334
1335 err_rx_trap_set:
1336         mlxsw_core_rx_listener_unregister(mlxsw_sx->core,
1337                                           &mlxsw_sx_rx_listener[i],
1338                                           mlxsw_sx);
1339 err_rx_listener_register:
1340         for (i--; i >= 0; i--) {
1341                 mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD,
1342                                     MLXSW_REG_HTGT_TRAP_GROUP_RX,
1343                                     mlxsw_sx_rx_listener[i].trap_id);
1344                 mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl);
1345
1346                 mlxsw_core_rx_listener_unregister(mlxsw_sx->core,
1347                                                   &mlxsw_sx_rx_listener[i],
1348                                                   mlxsw_sx);
1349         }
1350         return err;
1351 }
1352
1353 static void mlxsw_sx_traps_fini(struct mlxsw_sx *mlxsw_sx)
1354 {
1355         char hpkt_pl[MLXSW_REG_HPKT_LEN];
1356         int i;
1357
1358         for (i = 0; i < ARRAY_SIZE(mlxsw_sx_rx_listener); i++) {
1359                 mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD,
1360                                     MLXSW_REG_HTGT_TRAP_GROUP_RX,
1361                                     mlxsw_sx_rx_listener[i].trap_id);
1362                 mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl);
1363
1364                 mlxsw_core_rx_listener_unregister(mlxsw_sx->core,
1365                                                   &mlxsw_sx_rx_listener[i],
1366                                                   mlxsw_sx);
1367         }
1368 }
1369
1370 static int mlxsw_sx_flood_init(struct mlxsw_sx *mlxsw_sx)
1371 {
1372         char sfgc_pl[MLXSW_REG_SFGC_LEN];
1373         char sgcr_pl[MLXSW_REG_SGCR_LEN];
1374         char *smid_pl;
1375         char *sftr_pl;
1376         int err;
1377
1378         /* Due to FW bug, we must configure SMID. */
1379         smid_pl = kmalloc(MLXSW_REG_SMID_LEN, GFP_KERNEL);
1380         if (!smid_pl)
1381                 return -ENOMEM;
1382         mlxsw_reg_smid_pack(smid_pl, MLXSW_PORT_MID);
1383         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(smid), smid_pl);
1384         kfree(smid_pl);
1385         if (err)
1386                 return err;
1387
1388         /* Configure a flooding table, which includes only CPU port. */
1389         sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
1390         if (!sftr_pl)
1391                 return -ENOMEM;
1392         mlxsw_reg_sftr_pack(sftr_pl, 0, 0, MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 0);
1393         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sftr), sftr_pl);
1394         kfree(sftr_pl);
1395         if (err)
1396                 return err;
1397
1398         /* Flood different packet types using the flooding table. */
1399         mlxsw_reg_sfgc_pack(sfgc_pl,
1400                             MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST,
1401                             MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
1402                             MLXSW_REG_SFGC_TABLE_TYPE_SINGLE,
1403                             0);
1404         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl);
1405         if (err)
1406                 return err;
1407
1408         mlxsw_reg_sfgc_pack(sfgc_pl,
1409                             MLXSW_REG_SFGC_TYPE_BROADCAST,
1410                             MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
1411                             MLXSW_REG_SFGC_TABLE_TYPE_SINGLE,
1412                             0);
1413         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl);
1414         if (err)
1415                 return err;
1416
1417         mlxsw_reg_sfgc_pack(sfgc_pl,
1418                             MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP,
1419                             MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
1420                             MLXSW_REG_SFGC_TABLE_TYPE_SINGLE,
1421                             0);
1422         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl);
1423         if (err)
1424                 return err;
1425
1426         mlxsw_reg_sfgc_pack(sfgc_pl,
1427                             MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6,
1428                             MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
1429                             MLXSW_REG_SFGC_TABLE_TYPE_SINGLE,
1430                             0);
1431         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl);
1432         if (err)
1433                 return err;
1434
1435         mlxsw_reg_sfgc_pack(sfgc_pl,
1436                             MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4,
1437                             MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
1438                             MLXSW_REG_SFGC_TABLE_TYPE_SINGLE,
1439                             0);
1440         err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sfgc), sfgc_pl);
1441         if (err)
1442                 return err;
1443
1444         mlxsw_reg_sgcr_pack(sgcr_pl, true);
1445         return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sgcr), sgcr_pl);
1446 }
1447
1448 static int mlxsw_sx_init(void *priv, struct mlxsw_core *mlxsw_core,
1449                          const struct mlxsw_bus_info *mlxsw_bus_info)
1450 {
1451         struct mlxsw_sx *mlxsw_sx = priv;
1452         int err;
1453
1454         mlxsw_sx->core = mlxsw_core;
1455         mlxsw_sx->bus_info = mlxsw_bus_info;
1456
1457         err = mlxsw_sx_hw_id_get(mlxsw_sx);
1458         if (err) {
1459                 dev_err(mlxsw_sx->bus_info->dev, "Failed to get switch HW ID\n");
1460                 return err;
1461         }
1462
1463         err = mlxsw_sx_ports_create(mlxsw_sx);
1464         if (err) {
1465                 dev_err(mlxsw_sx->bus_info->dev, "Failed to create ports\n");
1466                 return err;
1467         }
1468
1469         err = mlxsw_sx_event_register(mlxsw_sx, MLXSW_TRAP_ID_PUDE);
1470         if (err) {
1471                 dev_err(mlxsw_sx->bus_info->dev, "Failed to register for PUDE events\n");
1472                 goto err_event_register;
1473         }
1474
1475         err = mlxsw_sx_traps_init(mlxsw_sx);
1476         if (err) {
1477                 dev_err(mlxsw_sx->bus_info->dev, "Failed to set traps for RX\n");
1478                 goto err_rx_listener_register;
1479         }
1480
1481         err = mlxsw_sx_flood_init(mlxsw_sx);
1482         if (err) {
1483                 dev_err(mlxsw_sx->bus_info->dev, "Failed to initialize flood tables\n");
1484                 goto err_flood_init;
1485         }
1486
1487         return 0;
1488
1489 err_flood_init:
1490         mlxsw_sx_traps_fini(mlxsw_sx);
1491 err_rx_listener_register:
1492         mlxsw_sx_event_unregister(mlxsw_sx, MLXSW_TRAP_ID_PUDE);
1493 err_event_register:
1494         mlxsw_sx_ports_remove(mlxsw_sx);
1495         return err;
1496 }
1497
1498 static void mlxsw_sx_fini(void *priv)
1499 {
1500         struct mlxsw_sx *mlxsw_sx = priv;
1501
1502         mlxsw_sx_traps_fini(mlxsw_sx);
1503         mlxsw_sx_event_unregister(mlxsw_sx, MLXSW_TRAP_ID_PUDE);
1504         mlxsw_sx_ports_remove(mlxsw_sx);
1505 }
1506
1507 static struct mlxsw_config_profile mlxsw_sx_config_profile = {
1508         .used_max_vepa_channels         = 1,
1509         .max_vepa_channels              = 0,
1510         .used_max_lag                   = 1,
1511         .max_lag                        = 64,
1512         .used_max_port_per_lag          = 1,
1513         .max_port_per_lag               = 16,
1514         .used_max_mid                   = 1,
1515         .max_mid                        = 7000,
1516         .used_max_pgt                   = 1,
1517         .max_pgt                        = 0,
1518         .used_max_system_port           = 1,
1519         .max_system_port                = 48000,
1520         .used_max_vlan_groups           = 1,
1521         .max_vlan_groups                = 127,
1522         .used_max_regions               = 1,
1523         .max_regions                    = 400,
1524         .used_flood_tables              = 1,
1525         .max_flood_tables               = 2,
1526         .max_vid_flood_tables           = 1,
1527         .used_flood_mode                = 1,
1528         .flood_mode                     = 3,
1529         .used_max_ib_mc                 = 1,
1530         .max_ib_mc                      = 0,
1531         .used_max_pkey                  = 1,
1532         .max_pkey                       = 0,
1533         .swid_config                    = {
1534                 {
1535                         .used_type      = 1,
1536                         .type           = MLXSW_PORT_SWID_TYPE_ETH,
1537                 }
1538         },
1539 };
1540
1541 static struct mlxsw_driver mlxsw_sx_driver = {
1542         .kind                   = MLXSW_DEVICE_KIND_SWITCHX2,
1543         .owner                  = THIS_MODULE,
1544         .priv_size              = sizeof(struct mlxsw_sx),
1545         .init                   = mlxsw_sx_init,
1546         .fini                   = mlxsw_sx_fini,
1547         .txhdr_construct        = mlxsw_sx_txhdr_construct,
1548         .txhdr_len              = MLXSW_TXHDR_LEN,
1549         .profile                = &mlxsw_sx_config_profile,
1550 };
1551
1552 static int __init mlxsw_sx_module_init(void)
1553 {
1554         return mlxsw_core_driver_register(&mlxsw_sx_driver);
1555 }
1556
1557 static void __exit mlxsw_sx_module_exit(void)
1558 {
1559         mlxsw_core_driver_unregister(&mlxsw_sx_driver);
1560 }
1561
1562 module_init(mlxsw_sx_module_init);
1563 module_exit(mlxsw_sx_module_exit);
1564
1565 MODULE_LICENSE("Dual BSD/GPL");
1566 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
1567 MODULE_DESCRIPTION("Mellanox SwitchX-2 driver");
1568 MODULE_MLXSW_DRIVER_ALIAS(MLXSW_DEVICE_KIND_SWITCHX2);