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