Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/ethernet/mellanox/mlxsw/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 379 kB image not shown  

Quelle  reg.h   Sprache: C

 
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
/* Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved */

#ifndef _MLXSW_REG_H
#define _MLXSW_REG_H

#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/bitops.h>
#include <linux/if_vlan.h>

#include "item.h"
#include "port.h"

struct mlxsw_reg_info {
 u16 id;
 u16 len; /* In u8 */
 const char *name;
};

#define MLXSW_REG_DEFINE(_name, _id, _len)    \
static const struct mlxsw_reg_info mlxsw_reg_##_name = {  \
 .id = _id,       \
 .len = _len,       \
 .name = #_name,       \
}

#define MLXSW_REG(type) (&mlxsw_reg_##type)
#define MLXSW_REG_LEN(type) MLXSW_REG(type)->len
#define MLXSW_REG_ZERO(type, payload) memset(payload, 0, MLXSW_REG(type)->len)

/* SGCR - Switch General Configuration Register
 * --------------------------------------------
 * This register is used for configuration of the switch capabilities.
 */

#define MLXSW_REG_SGCR_ID 0x2000
#define MLXSW_REG_SGCR_LEN 0x10

MLXSW_REG_DEFINE(sgcr, MLXSW_REG_SGCR_ID, MLXSW_REG_SGCR_LEN);

/* reg_sgcr_lag_lookup_pgt_base
 * Base address used for lookup in PGT table
 * Supported when CONFIG_PROFILE.lag_mode = 1
 * Note: when IGCR.ddd_lag_mode=0, the address shall be aligned to 8 entries.
 * Access: RW
 */

MLXSW_ITEM32(reg, sgcr, lag_lookup_pgt_base, 0x0C, 0, 16);

static inline void mlxsw_reg_sgcr_pack(char *payload, u16 lag_lookup_pgt_base)
{
 MLXSW_REG_ZERO(sgcr, payload);
 mlxsw_reg_sgcr_lag_lookup_pgt_base_set(payload, lag_lookup_pgt_base);
}

/* SPAD - Switch Physical Address Register
 * ---------------------------------------
 * The SPAD register configures the switch physical MAC address.
 */

#define MLXSW_REG_SPAD_ID 0x2002
#define MLXSW_REG_SPAD_LEN 0x10

MLXSW_REG_DEFINE(spad, MLXSW_REG_SPAD_ID, MLXSW_REG_SPAD_LEN);

/* reg_spad_base_mac
 * Base MAC address for the switch partitions.
 * Per switch partition MAC address is equal to:
 * base_mac + swid
 * Access: RW
 */

MLXSW_ITEM_BUF(reg, spad, base_mac, 0x02, 6);

/* SSPR - Switch System Port Record Register
 * -----------------------------------------
 * Configures the system port to local port mapping.
 */

#define MLXSW_REG_SSPR_ID 0x2008
#define MLXSW_REG_SSPR_LEN 0x8

MLXSW_REG_DEFINE(sspr, MLXSW_REG_SSPR_ID, MLXSW_REG_SSPR_LEN);

/* reg_sspr_m
 * Master - if set, then the record describes the master system port.
 * This is needed in case a local port is mapped into several system ports
 * (for multipathing). That number will be reported as the source system
 * port when packets are forwarded to the CPU. Only one master port is allowed
 * per local port.
 *
 * Note: Must be set for Spectrum.
 * Access: RW
 */

MLXSW_ITEM32(reg, sspr, m, 0x00, 31, 1);

/* reg_sspr_local_port
 * Local port number.
 *
 * Access: RW
 */

MLXSW_ITEM32_LP(reg, sspr, 0x00, 16, 0x00, 12);

/* reg_sspr_system_port
 * Unique identifier within the stacking domain that represents all the ports
 * that are available in the system (external ports).
 *
 * Currently, only single-ASIC configurations are supported, so we default to
 * 1:1 mapping between system ports and local ports.
 * Access: Index
 */

MLXSW_ITEM32(reg, sspr, system_port, 0x04, 0, 16);

static inline void mlxsw_reg_sspr_pack(char *payload, u16 local_port)
{
 MLXSW_REG_ZERO(sspr, payload);
 mlxsw_reg_sspr_m_set(payload, 1);
 mlxsw_reg_sspr_local_port_set(payload, local_port);
 mlxsw_reg_sspr_system_port_set(payload, local_port);
}

/* SFDAT - Switch Filtering Database Aging Time
 * --------------------------------------------
 * Controls the Switch aging time. Aging time is able to be set per Switch
 * Partition.
 */

#define MLXSW_REG_SFDAT_ID 0x2009
#define MLXSW_REG_SFDAT_LEN 0x8

MLXSW_REG_DEFINE(sfdat, MLXSW_REG_SFDAT_ID, MLXSW_REG_SFDAT_LEN);

/* reg_sfdat_swid
 * Switch partition ID.
 * Access: Index
 */

MLXSW_ITEM32(reg, sfdat, swid, 0x00, 24, 8);

/* reg_sfdat_age_time
 * Aging time in seconds
 * Min - 10 seconds
 * Max - 1,000,000 seconds
 * Default is 300 seconds.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfdat, age_time, 0x04, 0, 20);

static inline void mlxsw_reg_sfdat_pack(char *payload, u32 age_time)
{
 MLXSW_REG_ZERO(sfdat, payload);
 mlxsw_reg_sfdat_swid_set(payload, 0);
 mlxsw_reg_sfdat_age_time_set(payload, age_time);
}

/* SFD - Switch Filtering Database
 * -------------------------------
 * The following register defines the access to the filtering database.
 * The register supports querying, adding, removing and modifying the database.
 * The access is optimized for bulk updates in which case more than one
 * FDB record is present in the same command.
 */

#define MLXSW_REG_SFD_ID 0x200A
#define MLXSW_REG_SFD_BASE_LEN 0x10 /* base length, without records */
#define MLXSW_REG_SFD_REC_LEN 0x10 /* record length */
#define MLXSW_REG_SFD_REC_MAX_COUNT 64
#define MLXSW_REG_SFD_LEN (MLXSW_REG_SFD_BASE_LEN + \
      MLXSW_REG_SFD_REC_LEN * MLXSW_REG_SFD_REC_MAX_COUNT)

MLXSW_REG_DEFINE(sfd, MLXSW_REG_SFD_ID, MLXSW_REG_SFD_LEN);

/* reg_sfd_swid
 * Switch partition ID for queries. Reserved on Write.
 * Access: Index
 */

MLXSW_ITEM32(reg, sfd, swid, 0x00, 24, 8);

enum mlxsw_reg_sfd_op {
 /* Dump entire FDB a (process according to record_locator) */
 MLXSW_REG_SFD_OP_QUERY_DUMP = 0,
 /* Query records by {MAC, VID/FID} value */
 MLXSW_REG_SFD_OP_QUERY_QUERY = 1,
 /* Query and clear activity. Query records by {MAC, VID/FID} value */
 MLXSW_REG_SFD_OP_QUERY_QUERY_AND_CLEAR_ACTIVITY = 2,
 /* Test. Response indicates if each of the records could be
 * added to the FDB.
 */

 MLXSW_REG_SFD_OP_WRITE_TEST = 0,
 /* Add/modify. Aged-out records cannot be added. This command removes
 * the learning notification of the {MAC, VID/FID}. Response includes
 * the entries that were added to the FDB.
 */

 MLXSW_REG_SFD_OP_WRITE_EDIT = 1,
 /* Remove record by {MAC, VID/FID}. This command also removes
 * the learning notification and aged-out notifications
 * of the {MAC, VID/FID}. The response provides current (pre-removal)
 * entries as non-aged-out.
 */

 MLXSW_REG_SFD_OP_WRITE_REMOVE = 2,
 /* Remove learned notification by {MAC, VID/FID}. The response provides
 * the removed learning notification.
 */

 MLXSW_REG_SFD_OP_WRITE_REMOVE_NOTIFICATION = 2,
};

/* reg_sfd_op
 * Operation.
 * Access: OP
 */

MLXSW_ITEM32(reg, sfd, op, 0x04, 30, 2);

/* reg_sfd_record_locator
 * Used for querying the FDB. Use record_locator=0 to initiate the
 * query. When a record is returned, a new record_locator is
 * returned to be used in the subsequent query.
 * Reserved for database update.
 * Access: Index
 */

MLXSW_ITEM32(reg, sfd, record_locator, 0x04, 0, 30);

/* reg_sfd_num_rec
 * Request: Number of records to read/add/modify/remove
 * Response: Number of records read/added/replaced/removed
 * See above description for more details.
 * Ranges 0..64
 * Access: RW
 */

MLXSW_ITEM32(reg, sfd, num_rec, 0x08, 0, 8);

static inline void mlxsw_reg_sfd_pack(char *payload, enum mlxsw_reg_sfd_op op,
          u32 record_locator)
{
 MLXSW_REG_ZERO(sfd, payload);
 mlxsw_reg_sfd_op_set(payload, op);
 mlxsw_reg_sfd_record_locator_set(payload, record_locator);
}

/* reg_sfd_rec_swid
 * Switch partition ID.
 * Access: Index
 */

MLXSW_ITEM32_INDEXED(reg, sfd, rec_swid, MLXSW_REG_SFD_BASE_LEN, 24, 8,
       MLXSW_REG_SFD_REC_LEN, 0x00, false);

enum mlxsw_reg_sfd_rec_type {
 MLXSW_REG_SFD_REC_TYPE_UNICAST = 0x0,
 MLXSW_REG_SFD_REC_TYPE_UNICAST_LAG = 0x1,
 MLXSW_REG_SFD_REC_TYPE_MULTICAST = 0x2,
 MLXSW_REG_SFD_REC_TYPE_UNICAST_TUNNEL = 0xC,
};

/* reg_sfd_rec_type
 * FDB record type.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, rec_type, MLXSW_REG_SFD_BASE_LEN, 20, 4,
       MLXSW_REG_SFD_REC_LEN, 0x00, false);

enum mlxsw_reg_sfd_rec_policy {
 /* Replacement disabled, aging disabled. */
 MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY = 0,
 /* (mlag remote): Replacement enabled, aging disabled,
 * learning notification enabled on this port.
 */

 MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_MLAG = 1,
 /* (ingress device): Replacement enabled, aging enabled. */
 MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS = 3,
};

/* reg_sfd_rec_policy
 * Policy.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, rec_policy, MLXSW_REG_SFD_BASE_LEN, 18, 2,
       MLXSW_REG_SFD_REC_LEN, 0x00, false);

/* reg_sfd_rec_a
 * Activity. Set for new static entries. Set for static entries if a frame SMAC
 * lookup hits on the entry.
 * To clear the a bit, use "query and clear activity" op.
 * Access: RO
 */

MLXSW_ITEM32_INDEXED(reg, sfd, rec_a, MLXSW_REG_SFD_BASE_LEN, 16, 1,
       MLXSW_REG_SFD_REC_LEN, 0x00, false);

/* reg_sfd_rec_mac
 * MAC address.
 * Access: Index
 */

MLXSW_ITEM_BUF_INDEXED(reg, sfd, rec_mac, MLXSW_REG_SFD_BASE_LEN, 6,
         MLXSW_REG_SFD_REC_LEN, 0x02);

enum mlxsw_reg_sfd_rec_action {
 /* forward */
 MLXSW_REG_SFD_REC_ACTION_NOP = 0,
 /* forward and trap, trap_id is FDB_TRAP */
 MLXSW_REG_SFD_REC_ACTION_MIRROR_TO_CPU = 1,
 /* trap and do not forward, trap_id is FDB_TRAP */
 MLXSW_REG_SFD_REC_ACTION_TRAP = 2,
 /* forward to IP router */
 MLXSW_REG_SFD_REC_ACTION_FORWARD_IP_ROUTER = 3,
 MLXSW_REG_SFD_REC_ACTION_DISCARD_ERROR = 15,
};

/* reg_sfd_rec_action
 * Action to apply on the packet.
 * Note: Dynamic entries can only be configured with NOP action.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, rec_action, MLXSW_REG_SFD_BASE_LEN, 28, 4,
       MLXSW_REG_SFD_REC_LEN, 0x0C, false);

/* reg_sfd_uc_sub_port
 * VEPA channel on local port.
 * Valid only if local port is a non-stacking port. Must be 0 if multichannel
 * VEPA is not enabled.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_sub_port, MLXSW_REG_SFD_BASE_LEN, 16, 8,
       MLXSW_REG_SFD_REC_LEN, 0x08, false);

/* reg_sfd_uc_set_vid
 * Set VID.
 * 0 - Do not update VID.
 * 1 - Set VID.
 * For Spectrum-2 when set_vid=0 and smpe_valid=1, the smpe will modify the vid.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used.
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_set_vid, MLXSW_REG_SFD_BASE_LEN, 31, 1,
       MLXSW_REG_SFD_REC_LEN, 0x08, false);

/* reg_sfd_uc_fid_vid
 * Filtering ID or VLAN ID
 * For SwitchX and SwitchX-2:
 * - Dynamic entries (policy 2,3) use FID
 * - Static entries (policy 0) use VID
 * - When independent learning is configured, VID=FID
 * For Spectrum: use FID for both Dynamic and Static entries.
 * VID should not be used.
 * Access: Index
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_fid_vid, MLXSW_REG_SFD_BASE_LEN, 0, 16,
       MLXSW_REG_SFD_REC_LEN, 0x08, false);

/* reg_sfd_uc_vid
 * New VID when set_vid=1.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used and when set_vid=0.
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_vid, MLXSW_REG_SFD_BASE_LEN, 16, 12,
       MLXSW_REG_SFD_REC_LEN, 0x0C, false);

/* reg_sfd_uc_system_port
 * Unique port identifier for the final destination of the packet.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_system_port, MLXSW_REG_SFD_BASE_LEN, 0, 16,
       MLXSW_REG_SFD_REC_LEN, 0x0C, false);

static inline void mlxsw_reg_sfd_rec_pack(char *payload, int rec_index,
       enum mlxsw_reg_sfd_rec_type rec_type,
       const char *mac,
       enum mlxsw_reg_sfd_rec_action action)
{
 u8 num_rec = mlxsw_reg_sfd_num_rec_get(payload);

 if (rec_index >= num_rec)
  mlxsw_reg_sfd_num_rec_set(payload, rec_index + 1);
 mlxsw_reg_sfd_rec_swid_set(payload, rec_index, 0);
 mlxsw_reg_sfd_rec_type_set(payload, rec_index, rec_type);
 mlxsw_reg_sfd_rec_mac_memcpy_to(payload, rec_index, mac);
 mlxsw_reg_sfd_rec_action_set(payload, rec_index, action);
}

static inline void mlxsw_reg_sfd_uc_pack(char *payload, int rec_index,
      enum mlxsw_reg_sfd_rec_policy policy,
      const char *mac, u16 fid_vid, u16 vid,
      enum mlxsw_reg_sfd_rec_action action,
      u16 local_port)
{
 mlxsw_reg_sfd_rec_pack(payload, rec_index,
          MLXSW_REG_SFD_REC_TYPE_UNICAST, mac, action);
 mlxsw_reg_sfd_rec_policy_set(payload, rec_index, policy);
 mlxsw_reg_sfd_uc_sub_port_set(payload, rec_index, 0);
 mlxsw_reg_sfd_uc_fid_vid_set(payload, rec_index, fid_vid);
 mlxsw_reg_sfd_uc_set_vid_set(payload, rec_index, vid ? true : false);
 mlxsw_reg_sfd_uc_vid_set(payload, rec_index, vid);
 mlxsw_reg_sfd_uc_system_port_set(payload, rec_index, local_port);
}

/* reg_sfd_uc_lag_sub_port
 * LAG sub port.
 * Must be 0 if multichannel VEPA is not enabled.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_lag_sub_port, MLXSW_REG_SFD_BASE_LEN, 16, 8,
       MLXSW_REG_SFD_REC_LEN, 0x08, false);

/* reg_sfd_uc_lag_set_vid
 * Set VID.
 * 0 - Do not update VID.
 * 1 - Set VID.
 * For Spectrum-2 when set_vid=0 and smpe_valid=1, the smpe will modify the vid.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used.
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_lag_set_vid, MLXSW_REG_SFD_BASE_LEN, 31, 1,
       MLXSW_REG_SFD_REC_LEN, 0x08, false);

/* reg_sfd_uc_lag_fid_vid
 * Filtering ID or VLAN ID
 * For SwitchX and SwitchX-2:
 * - Dynamic entries (policy 2,3) use FID
 * - Static entries (policy 0) use VID
 * - When independent learning is configured, VID=FID
 * For Spectrum: use FID for both Dynamic and Static entries.
 * VID should not be used.
 * Access: Index
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_lag_fid_vid, MLXSW_REG_SFD_BASE_LEN, 0, 16,
       MLXSW_REG_SFD_REC_LEN, 0x08, false);

/* reg_sfd_uc_lag_lag_vid
 * New vlan ID.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used and set_vid=0.
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_lag_lag_vid, MLXSW_REG_SFD_BASE_LEN, 16, 12,
       MLXSW_REG_SFD_REC_LEN, 0x0C, false);

/* reg_sfd_uc_lag_lag_id
 * LAG Identifier - pointer into the LAG descriptor table.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_lag_lag_id, MLXSW_REG_SFD_BASE_LEN, 0, 10,
       MLXSW_REG_SFD_REC_LEN, 0x0C, false);

static inline void
mlxsw_reg_sfd_uc_lag_pack(char *payload, int rec_index,
     enum mlxsw_reg_sfd_rec_policy policy,
     const char *mac, u16 fid_vid,
     enum mlxsw_reg_sfd_rec_action action, u16 lag_vid,
     u16 lag_id)
{
 mlxsw_reg_sfd_rec_pack(payload, rec_index,
          MLXSW_REG_SFD_REC_TYPE_UNICAST_LAG,
          mac, action);
 mlxsw_reg_sfd_rec_policy_set(payload, rec_index, policy);
 mlxsw_reg_sfd_uc_lag_sub_port_set(payload, rec_index, 0);
 mlxsw_reg_sfd_uc_lag_fid_vid_set(payload, rec_index, fid_vid);
 mlxsw_reg_sfd_uc_lag_set_vid_set(payload, rec_index, true);
 mlxsw_reg_sfd_uc_lag_lag_vid_set(payload, rec_index, lag_vid);
 mlxsw_reg_sfd_uc_lag_lag_id_set(payload, rec_index, lag_id);
}

/* reg_sfd_mc_pgi
 *
 * Multicast port group index - index into the port group table.
 * Value 0x1FFF indicates the pgi should point to the MID entry.
 * For Spectrum this value must be set to 0x1FFF
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, mc_pgi, MLXSW_REG_SFD_BASE_LEN, 16, 13,
       MLXSW_REG_SFD_REC_LEN, 0x08, false);

/* reg_sfd_mc_fid_vid
 *
 * Filtering ID or VLAN ID
 * Access: Index
 */

MLXSW_ITEM32_INDEXED(reg, sfd, mc_fid_vid, MLXSW_REG_SFD_BASE_LEN, 0, 16,
       MLXSW_REG_SFD_REC_LEN, 0x08, false);

/* reg_sfd_mc_mid
 *
 * Multicast identifier - global identifier that represents the multicast
 * group across all devices.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, mc_mid, MLXSW_REG_SFD_BASE_LEN, 0, 16,
       MLXSW_REG_SFD_REC_LEN, 0x0C, false);

static inline void
mlxsw_reg_sfd_mc_pack(char *payload, int rec_index,
        const char *mac, u16 fid_vid,
        enum mlxsw_reg_sfd_rec_action action, u16 mid)
{
 mlxsw_reg_sfd_rec_pack(payload, rec_index,
          MLXSW_REG_SFD_REC_TYPE_MULTICAST, mac, action);
 mlxsw_reg_sfd_mc_pgi_set(payload, rec_index, 0x1FFF);
 mlxsw_reg_sfd_mc_fid_vid_set(payload, rec_index, fid_vid);
 mlxsw_reg_sfd_mc_mid_set(payload, rec_index, mid);
}

/* reg_sfd_uc_tunnel_uip_msb
 * When protocol is IPv4, the most significant byte of the underlay IPv4
 * destination IP.
 * When protocol is IPv6, reserved.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_tunnel_uip_msb, MLXSW_REG_SFD_BASE_LEN, 24,
       8, MLXSW_REG_SFD_REC_LEN, 0x08, false);

/* reg_sfd_uc_tunnel_fid
 * Filtering ID.
 * Access: Index
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_tunnel_fid, MLXSW_REG_SFD_BASE_LEN, 0, 16,
       MLXSW_REG_SFD_REC_LEN, 0x08, false);

enum mlxsw_reg_sfd_uc_tunnel_protocol {
 MLXSW_REG_SFD_UC_TUNNEL_PROTOCOL_IPV4,
 MLXSW_REG_SFD_UC_TUNNEL_PROTOCOL_IPV6,
};

/* reg_sfd_uc_tunnel_protocol
 * IP protocol.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_tunnel_protocol, MLXSW_REG_SFD_BASE_LEN, 27,
       1, MLXSW_REG_SFD_REC_LEN, 0x0C, false);

/* reg_sfd_uc_tunnel_uip_lsb
 * When protocol is IPv4, the least significant bytes of the underlay
 * IPv4 destination IP.
 * When protocol is IPv6, pointer to the underlay IPv6 destination IP
 * which is configured by RIPS.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sfd, uc_tunnel_uip_lsb, MLXSW_REG_SFD_BASE_LEN, 0,
       24, MLXSW_REG_SFD_REC_LEN, 0x0C, false);

static inline void
mlxsw_reg_sfd_uc_tunnel_pack(char *payload, int rec_index,
        enum mlxsw_reg_sfd_rec_policy policy,
        const char *mac, u16 fid,
        enum mlxsw_reg_sfd_rec_action action,
        enum mlxsw_reg_sfd_uc_tunnel_protocol proto)
{
 mlxsw_reg_sfd_rec_pack(payload, rec_index,
          MLXSW_REG_SFD_REC_TYPE_UNICAST_TUNNEL, mac,
          action);
 mlxsw_reg_sfd_rec_policy_set(payload, rec_index, policy);
 mlxsw_reg_sfd_uc_tunnel_fid_set(payload, rec_index, fid);
 mlxsw_reg_sfd_uc_tunnel_protocol_set(payload, rec_index, proto);
}

static inline void
mlxsw_reg_sfd_uc_tunnel_pack4(char *payload, int rec_index,
         enum mlxsw_reg_sfd_rec_policy policy,
         const char *mac, u16 fid,
         enum mlxsw_reg_sfd_rec_action action, u32 uip)
{
 mlxsw_reg_sfd_uc_tunnel_uip_msb_set(payload, rec_index, uip >> 24);
 mlxsw_reg_sfd_uc_tunnel_uip_lsb_set(payload, rec_index, uip);
 mlxsw_reg_sfd_uc_tunnel_pack(payload, rec_index, policy, mac, fid,
         action,
         MLXSW_REG_SFD_UC_TUNNEL_PROTOCOL_IPV4);
}

static inline void
mlxsw_reg_sfd_uc_tunnel_pack6(char *payload, int rec_index, const char *mac,
         u16 fid, enum mlxsw_reg_sfd_rec_action action,
         u32 uip_ptr)
{
 mlxsw_reg_sfd_uc_tunnel_uip_lsb_set(payload, rec_index, uip_ptr);
 /* Only static policy is supported for IPv6 unicast tunnel entry. */
 mlxsw_reg_sfd_uc_tunnel_pack(payload, rec_index,
         MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY,
         mac, fid, action,
         MLXSW_REG_SFD_UC_TUNNEL_PROTOCOL_IPV6);
}

enum mlxsw_reg_tunnel_port {
 MLXSW_REG_TUNNEL_PORT_NVE,
 MLXSW_REG_TUNNEL_PORT_VPLS,
 MLXSW_REG_TUNNEL_PORT_FLEX_TUNNEL0,
 MLXSW_REG_TUNNEL_PORT_FLEX_TUNNEL1,
};

/* SFN - Switch FDB Notification Register
 * -------------------------------------------
 * The switch provides notifications on newly learned FDB entries and
 * aged out entries. The notifications can be polled by software.
 */

#define MLXSW_REG_SFN_ID 0x200B
#define MLXSW_REG_SFN_BASE_LEN 0x10 /* base length, without records */
#define MLXSW_REG_SFN_REC_LEN 0x10 /* record length */
#define MLXSW_REG_SFN_REC_MAX_COUNT 64
#define MLXSW_REG_SFN_LEN (MLXSW_REG_SFN_BASE_LEN + \
      MLXSW_REG_SFN_REC_LEN * MLXSW_REG_SFN_REC_MAX_COUNT)

MLXSW_REG_DEFINE(sfn, MLXSW_REG_SFN_ID, MLXSW_REG_SFN_LEN);

/* reg_sfn_swid
 * Switch partition ID.
 * Access: Index
 */

MLXSW_ITEM32(reg, sfn, swid, 0x00, 24, 8);

/* reg_sfn_end
 * Forces the current session to end.
 * Access: OP
 */

MLXSW_ITEM32(reg, sfn, end, 0x04, 20, 1);

/* reg_sfn_num_rec
 * Request: Number of learned notifications and aged-out notification
 * records requested.
 * Response: Number of notification records returned (must be smaller
 * than or equal to the value requested)
 * Ranges 0..64
 * Access: OP
 */

MLXSW_ITEM32(reg, sfn, num_rec, 0x04, 0, 8);

static inline void mlxsw_reg_sfn_pack(char *payload)
{
 MLXSW_REG_ZERO(sfn, payload);
 mlxsw_reg_sfn_swid_set(payload, 0);
 mlxsw_reg_sfn_end_set(payload, 0);
 mlxsw_reg_sfn_num_rec_set(payload, MLXSW_REG_SFN_REC_MAX_COUNT);
}

/* reg_sfn_rec_swid
 * Switch partition ID.
 * Access: RO
 */

MLXSW_ITEM32_INDEXED(reg, sfn, rec_swid, MLXSW_REG_SFN_BASE_LEN, 24, 8,
       MLXSW_REG_SFN_REC_LEN, 0x00, false);

enum mlxsw_reg_sfn_rec_type {
 /* MAC addresses learned on a regular port. */
 MLXSW_REG_SFN_REC_TYPE_LEARNED_MAC = 0x5,
 /* MAC addresses learned on a LAG port. */
 MLXSW_REG_SFN_REC_TYPE_LEARNED_MAC_LAG = 0x6,
 /* Aged-out MAC address on a regular port. */
 MLXSW_REG_SFN_REC_TYPE_AGED_OUT_MAC = 0x7,
 /* Aged-out MAC address on a LAG port. */
 MLXSW_REG_SFN_REC_TYPE_AGED_OUT_MAC_LAG = 0x8,
 /* Learned unicast tunnel record. */
 MLXSW_REG_SFN_REC_TYPE_LEARNED_UNICAST_TUNNEL = 0xD,
 /* Aged-out unicast tunnel record. */
 MLXSW_REG_SFN_REC_TYPE_AGED_OUT_UNICAST_TUNNEL = 0xE,
};

/* reg_sfn_rec_type
 * Notification record type.
 * Access: RO
 */

MLXSW_ITEM32_INDEXED(reg, sfn, rec_type, MLXSW_REG_SFN_BASE_LEN, 20, 4,
       MLXSW_REG_SFN_REC_LEN, 0x00, false);

/* reg_sfn_rec_mac
 * MAC address.
 * Access: RO
 */

MLXSW_ITEM_BUF_INDEXED(reg, sfn, rec_mac, MLXSW_REG_SFN_BASE_LEN, 6,
         MLXSW_REG_SFN_REC_LEN, 0x02);

/* reg_sfn_mac_sub_port
 * VEPA channel on the local port.
 * 0 if multichannel VEPA is not enabled.
 * Access: RO
 */

MLXSW_ITEM32_INDEXED(reg, sfn, mac_sub_port, MLXSW_REG_SFN_BASE_LEN, 16, 8,
       MLXSW_REG_SFN_REC_LEN, 0x08, false);

/* reg_sfn_mac_fid
 * Filtering identifier.
 * Access: RO
 */

MLXSW_ITEM32_INDEXED(reg, sfn, mac_fid, MLXSW_REG_SFN_BASE_LEN, 0, 16,
       MLXSW_REG_SFN_REC_LEN, 0x08, false);

/* reg_sfn_mac_system_port
 * Unique port identifier for the final destination of the packet.
 * Access: RO
 */

MLXSW_ITEM32_INDEXED(reg, sfn, mac_system_port, MLXSW_REG_SFN_BASE_LEN, 0, 16,
       MLXSW_REG_SFN_REC_LEN, 0x0C, false);

static inline void mlxsw_reg_sfn_mac_unpack(char *payload, int rec_index,
         char *mac, u16 *p_vid,
         u16 *p_local_port)
{
 mlxsw_reg_sfn_rec_mac_memcpy_from(payload, rec_index, mac);
 *p_vid = mlxsw_reg_sfn_mac_fid_get(payload, rec_index);
 *p_local_port = mlxsw_reg_sfn_mac_system_port_get(payload, rec_index);
}

/* reg_sfn_mac_lag_lag_id
 * LAG ID (pointer into the LAG descriptor table).
 * Access: RO
 */

MLXSW_ITEM32_INDEXED(reg, sfn, mac_lag_lag_id, MLXSW_REG_SFN_BASE_LEN, 0, 10,
       MLXSW_REG_SFN_REC_LEN, 0x0C, false);

static inline void mlxsw_reg_sfn_mac_lag_unpack(char *payload, int rec_index,
      char *mac, u16 *p_vid,
      u16 *p_lag_id)
{
 mlxsw_reg_sfn_rec_mac_memcpy_from(payload, rec_index, mac);
 *p_vid = mlxsw_reg_sfn_mac_fid_get(payload, rec_index);
 *p_lag_id = mlxsw_reg_sfn_mac_lag_lag_id_get(payload, rec_index);
}

/* reg_sfn_uc_tunnel_uip_msb
 * When protocol is IPv4, the most significant byte of the underlay IPv4
 * address of the remote VTEP.
 * When protocol is IPv6, reserved.
 * Access: RO
 */

MLXSW_ITEM32_INDEXED(reg, sfn, uc_tunnel_uip_msb, MLXSW_REG_SFN_BASE_LEN, 24,
       8, MLXSW_REG_SFN_REC_LEN, 0x08, false);

enum mlxsw_reg_sfn_uc_tunnel_protocol {
 MLXSW_REG_SFN_UC_TUNNEL_PROTOCOL_IPV4,
 MLXSW_REG_SFN_UC_TUNNEL_PROTOCOL_IPV6,
};

/* reg_sfn_uc_tunnel_protocol
 * IP protocol.
 * Access: RO
 */

MLXSW_ITEM32_INDEXED(reg, sfn, uc_tunnel_protocol, MLXSW_REG_SFN_BASE_LEN, 27,
       1, MLXSW_REG_SFN_REC_LEN, 0x0C, false);

/* reg_sfn_uc_tunnel_uip_lsb
 * When protocol is IPv4, the least significant bytes of the underlay
 * IPv4 address of the remote VTEP.
 * When protocol is IPv6, ipv6_id to be queried from TNIPSD.
 * Access: RO
 */

MLXSW_ITEM32_INDEXED(reg, sfn, uc_tunnel_uip_lsb, MLXSW_REG_SFN_BASE_LEN, 0,
       24, MLXSW_REG_SFN_REC_LEN, 0x0C, false);

/* reg_sfn_uc_tunnel_port
 * Tunnel port.
 * Reserved on Spectrum.
 * Access: RO
 */

MLXSW_ITEM32_INDEXED(reg, sfn, tunnel_port, MLXSW_REG_SFN_BASE_LEN, 0, 4,
       MLXSW_REG_SFN_REC_LEN, 0x10, false);

static inline void
mlxsw_reg_sfn_uc_tunnel_unpack(char *payload, int rec_index, char *mac,
          u16 *p_fid, u32 *p_uip,
          enum mlxsw_reg_sfn_uc_tunnel_protocol *p_proto)
{
 u32 uip_msb, uip_lsb;

 mlxsw_reg_sfn_rec_mac_memcpy_from(payload, rec_index, mac);
 *p_fid = mlxsw_reg_sfn_mac_fid_get(payload, rec_index);
 uip_msb = mlxsw_reg_sfn_uc_tunnel_uip_msb_get(payload, rec_index);
 uip_lsb = mlxsw_reg_sfn_uc_tunnel_uip_lsb_get(payload, rec_index);
 *p_uip = uip_msb << 24 | uip_lsb;
 *p_proto = mlxsw_reg_sfn_uc_tunnel_protocol_get(payload, rec_index);
}

/* SPMS - Switch Port MSTP/RSTP State Register
 * -------------------------------------------
 * Configures the spanning tree state of a physical port.
 */

#define MLXSW_REG_SPMS_ID 0x200D
#define MLXSW_REG_SPMS_LEN 0x404

MLXSW_REG_DEFINE(spms, MLXSW_REG_SPMS_ID, MLXSW_REG_SPMS_LEN);

/* reg_spms_local_port
 * Local port number.
 * Access: Index
 */

MLXSW_ITEM32_LP(reg, spms, 0x00, 16, 0x00, 12);

enum mlxsw_reg_spms_state {
 MLXSW_REG_SPMS_STATE_NO_CHANGE,
 MLXSW_REG_SPMS_STATE_DISCARDING,
 MLXSW_REG_SPMS_STATE_LEARNING,
 MLXSW_REG_SPMS_STATE_FORWARDING,
};

/* reg_spms_state
 * Spanning tree state of each VLAN ID (VID) of the local port.
 * 0 - Do not change spanning tree state (used only when writing).
 * 1 - Discarding. No learning or forwarding to/from this port (default).
 * 2 - Learning. Port is learning, but not forwarding.
 * 3 - Forwarding. Port is learning and forwarding.
 * Access: RW
 */

MLXSW_ITEM_BIT_ARRAY(reg, spms, state, 0x04, 0x400, 2);

static inline void mlxsw_reg_spms_pack(char *payload, u16 local_port)
{
 MLXSW_REG_ZERO(spms, payload);
 mlxsw_reg_spms_local_port_set(payload, local_port);
}

static inline void mlxsw_reg_spms_vid_pack(char *payload, u16 vid,
        enum mlxsw_reg_spms_state state)
{
 mlxsw_reg_spms_state_set(payload, vid, state);
}

/* SPVID - Switch Port VID
 * -----------------------
 * The switch port VID configures the default VID for a port.
 */

#define MLXSW_REG_SPVID_ID 0x200E
#define MLXSW_REG_SPVID_LEN 0x08

MLXSW_REG_DEFINE(spvid, MLXSW_REG_SPVID_ID, MLXSW_REG_SPVID_LEN);

/* reg_spvid_tport
 * Port is tunnel port.
 * Reserved when SwitchX/-2 or Spectrum-1.
 * Access: Index
 */

MLXSW_ITEM32(reg, spvid, tport, 0x00, 24, 1);

/* reg_spvid_local_port
 * When tport = 0: Local port number. Not supported for CPU port.
 * When tport = 1: Tunnel port.
 * Access: Index
 */

MLXSW_ITEM32_LP(reg, spvid, 0x00, 16, 0x00, 12);

/* reg_spvid_sub_port
 * Virtual port within the physical port.
 * Should be set to 0 when virtual ports are not enabled on the port.
 * Access: Index
 */

MLXSW_ITEM32(reg, spvid, sub_port, 0x00, 8, 8);

/* reg_spvid_egr_et_set
 * When VLAN is pushed at ingress (for untagged packets or for
 * QinQ push mode) then the EtherType is decided at the egress port.
 * Reserved when Spectrum-1.
 * Access: RW
 */

MLXSW_ITEM32(reg, spvid, egr_et_set, 0x04, 24, 1);

/* reg_spvid_et_vlan
 * EtherType used for when VLAN is pushed at ingress (for untagged
 * packets or for QinQ push mode).
 * 0: ether_type0 - (default)
 * 1: ether_type1
 * 2: ether_type2 - Reserved when Spectrum-1, supported by Spectrum-2
 * Ethertype IDs are configured by SVER.
 * Reserved when egr_et_set = 1.
 * Access: RW
 */

MLXSW_ITEM32(reg, spvid, et_vlan, 0x04, 16, 2);

/* reg_spvid_pvid
 * Port default VID
 * Access: RW
 */

MLXSW_ITEM32(reg, spvid, pvid, 0x04, 0, 12);

static inline void mlxsw_reg_spvid_pack(char *payload, u16 local_port, u16 pvid,
     u8 et_vlan)
{
 MLXSW_REG_ZERO(spvid, payload);
 mlxsw_reg_spvid_local_port_set(payload, local_port);
 mlxsw_reg_spvid_pvid_set(payload, pvid);
 mlxsw_reg_spvid_et_vlan_set(payload, et_vlan);
}

/* SPVM - Switch Port VLAN Membership
 * ----------------------------------
 * The Switch Port VLAN Membership register configures the VLAN membership
 * of a port in a VLAN denoted by VID. VLAN membership is managed per
 * virtual port. The register can be used to add and remove VID(s) from a port.
 */

#define MLXSW_REG_SPVM_ID 0x200F
#define MLXSW_REG_SPVM_BASE_LEN 0x04 /* base length, without records */
#define MLXSW_REG_SPVM_REC_LEN 0x04 /* record length */
#define MLXSW_REG_SPVM_REC_MAX_COUNT 255
#define MLXSW_REG_SPVM_LEN (MLXSW_REG_SPVM_BASE_LEN + \
      MLXSW_REG_SPVM_REC_LEN * MLXSW_REG_SPVM_REC_MAX_COUNT)

MLXSW_REG_DEFINE(spvm, MLXSW_REG_SPVM_ID, MLXSW_REG_SPVM_LEN);

/* reg_spvm_pt
 * Priority tagged. If this bit is set, packets forwarded to the port with
 * untagged VLAN membership (u bit is set) will be tagged with priority tag
 * (VID=0)
 * Access: RW
 */

MLXSW_ITEM32(reg, spvm, pt, 0x00, 31, 1);

/* reg_spvm_pte
 * Priority Tagged Update Enable. On Write operations, if this bit is cleared,
 * the pt bit will NOT be updated. To update the pt bit, pte must be set.
 * Access: WO
 */

MLXSW_ITEM32(reg, spvm, pte, 0x00, 30, 1);

/* reg_spvm_local_port
 * Local port number.
 * Access: Index
 */

MLXSW_ITEM32_LP(reg, spvm, 0x00, 16, 0x00, 12);

/* reg_spvm_sub_port
 * Virtual port within the physical port.
 * Should be set to 0 when virtual ports are not enabled on the port.
 * Access: Index
 */

MLXSW_ITEM32(reg, spvm, sub_port, 0x00, 8, 8);

/* reg_spvm_num_rec
 * Number of records to update. Each record contains: i, e, u, vid.
 * Access: OP
 */

MLXSW_ITEM32(reg, spvm, num_rec, 0x00, 0, 8);

/* reg_spvm_rec_i
 * Ingress membership in VLAN ID.
 * Access: Index
 */

MLXSW_ITEM32_INDEXED(reg, spvm, rec_i,
       MLXSW_REG_SPVM_BASE_LEN, 14, 1,
       MLXSW_REG_SPVM_REC_LEN, 0, false);

/* reg_spvm_rec_e
 * Egress membership in VLAN ID.
 * Access: Index
 */

MLXSW_ITEM32_INDEXED(reg, spvm, rec_e,
       MLXSW_REG_SPVM_BASE_LEN, 13, 1,
       MLXSW_REG_SPVM_REC_LEN, 0, false);

/* reg_spvm_rec_u
 * Untagged - port is an untagged member - egress transmission uses untagged
 * frames on VID<n>
 * Access: Index
 */

MLXSW_ITEM32_INDEXED(reg, spvm, rec_u,
       MLXSW_REG_SPVM_BASE_LEN, 12, 1,
       MLXSW_REG_SPVM_REC_LEN, 0, false);

/* reg_spvm_rec_vid
 * Egress membership in VLAN ID.
 * Access: Index
 */

MLXSW_ITEM32_INDEXED(reg, spvm, rec_vid,
       MLXSW_REG_SPVM_BASE_LEN, 0, 12,
       MLXSW_REG_SPVM_REC_LEN, 0, false);

static inline void mlxsw_reg_spvm_pack(char *payload, u16 local_port,
           u16 vid_begin, u16 vid_end,
           bool is_member, bool untagged)
{
 int size = vid_end - vid_begin + 1;
 int i;

 MLXSW_REG_ZERO(spvm, payload);
 mlxsw_reg_spvm_local_port_set(payload, local_port);
 mlxsw_reg_spvm_num_rec_set(payload, size);

 for (i = 0; i < size; i++) {
  mlxsw_reg_spvm_rec_i_set(payload, i, is_member);
  mlxsw_reg_spvm_rec_e_set(payload, i, is_member);
  mlxsw_reg_spvm_rec_u_set(payload, i, untagged);
  mlxsw_reg_spvm_rec_vid_set(payload, i, vid_begin + i);
 }
}

/* SPAFT - Switch Port Acceptable Frame Types
 * ------------------------------------------
 * The Switch Port Acceptable Frame Types register configures the frame
 * admittance of the port.
 */

#define MLXSW_REG_SPAFT_ID 0x2010
#define MLXSW_REG_SPAFT_LEN 0x08

MLXSW_REG_DEFINE(spaft, MLXSW_REG_SPAFT_ID, MLXSW_REG_SPAFT_LEN);

/* reg_spaft_local_port
 * Local port number.
 * Access: Index
 *
 * Note: CPU port is not supported (all tag types are allowed).
 */

MLXSW_ITEM32_LP(reg, spaft, 0x00, 16, 0x00, 12);

/* reg_spaft_sub_port
 * Virtual port within the physical port.
 * Should be set to 0 when virtual ports are not enabled on the port.
 * Access: RW
 */

MLXSW_ITEM32(reg, spaft, sub_port, 0x00, 8, 8);

/* reg_spaft_allow_untagged
 * When set, untagged frames on the ingress are allowed (default).
 * Access: RW
 */

MLXSW_ITEM32(reg, spaft, allow_untagged, 0x04, 31, 1);

/* reg_spaft_allow_prio_tagged
 * When set, priority tagged frames on the ingress are allowed (default).
 * Access: RW
 */

MLXSW_ITEM32(reg, spaft, allow_prio_tagged, 0x04, 30, 1);

/* reg_spaft_allow_tagged
 * When set, tagged frames on the ingress are allowed (default).
 * Access: RW
 */

MLXSW_ITEM32(reg, spaft, allow_tagged, 0x04, 29, 1);

static inline void mlxsw_reg_spaft_pack(char *payload, u16 local_port,
     bool allow_untagged)
{
 MLXSW_REG_ZERO(spaft, payload);
 mlxsw_reg_spaft_local_port_set(payload, local_port);
 mlxsw_reg_spaft_allow_untagged_set(payload, allow_untagged);
 mlxsw_reg_spaft_allow_prio_tagged_set(payload, allow_untagged);
 mlxsw_reg_spaft_allow_tagged_set(payload, true);
}

/* SFGC - Switch Flooding Group Configuration
 * ------------------------------------------
 * The following register controls the association of flooding tables and MIDs
 * to packet types used for flooding.
 *
 * Reserved when CONFIG_PROFILE.flood_mode = CFF.
 */

#define MLXSW_REG_SFGC_ID 0x2011
#define MLXSW_REG_SFGC_LEN 0x14

MLXSW_REG_DEFINE(sfgc, MLXSW_REG_SFGC_ID, MLXSW_REG_SFGC_LEN);

enum mlxsw_reg_sfgc_type {
 MLXSW_REG_SFGC_TYPE_BROADCAST,
 MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST,
 MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4,
 MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6,
 MLXSW_REG_SFGC_TYPE_RESERVED,
 MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP,
 MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL,
 MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST,
 MLXSW_REG_SFGC_TYPE_MAX,
};

/* reg_sfgc_type
 * The traffic type to reach the flooding table.
 * Access: Index
 */

MLXSW_ITEM32(reg, sfgc, type, 0x00, 0, 4);

/* bridge_type is used in SFGC and SFMR. */
enum mlxsw_reg_bridge_type {
 MLXSW_REG_BRIDGE_TYPE_0 = 0, /* Used for .1q FIDs. */
 MLXSW_REG_BRIDGE_TYPE_1 = 1, /* Used for .1d FIDs. */
};

/* reg_sfgc_bridge_type
 * Access: Index
 *
 * Note: SwitchX-2 only supports 802.1Q mode.
 */

MLXSW_ITEM32(reg, sfgc, bridge_type, 0x04, 24, 3);

enum mlxsw_flood_table_type {
 MLXSW_REG_SFGC_TABLE_TYPE_VID = 1,
 MLXSW_REG_SFGC_TABLE_TYPE_SINGLE = 2,
 MLXSW_REG_SFGC_TABLE_TYPE_ANY = 0,
 MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET = 3,
 MLXSW_REG_SFGC_TABLE_TYPE_FID = 4,
};

/* reg_sfgc_table_type
 * See mlxsw_flood_table_type
 * Access: RW
 *
 * Note: FID offset and FID types are not supported in SwitchX-2.
 */

MLXSW_ITEM32(reg, sfgc, table_type, 0x04, 16, 3);

/* reg_sfgc_flood_table
 * Flooding table index to associate with the specific type on the specific
 * switch partition.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfgc, flood_table, 0x04, 0, 6);

/* reg_sfgc_counter_set_type
 * Counter Set Type for flow counters.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfgc, counter_set_type, 0x0C, 24, 8);

/* reg_sfgc_counter_index
 * Counter Index for flow counters.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfgc, counter_index, 0x0C, 0, 24);

/* reg_sfgc_mid_base
 * MID Base.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used.
 */

MLXSW_ITEM32(reg, sfgc, mid_base, 0x10, 0, 16);

static inline void
mlxsw_reg_sfgc_pack(char *payload, enum mlxsw_reg_sfgc_type type,
      enum mlxsw_reg_bridge_type bridge_type,
      enum mlxsw_flood_table_type table_type,
      unsigned int flood_table, u16 mid_base)
{
 MLXSW_REG_ZERO(sfgc, payload);
 mlxsw_reg_sfgc_type_set(payload, type);
 mlxsw_reg_sfgc_bridge_type_set(payload, bridge_type);
 mlxsw_reg_sfgc_table_type_set(payload, table_type);
 mlxsw_reg_sfgc_flood_table_set(payload, flood_table);
 mlxsw_reg_sfgc_mid_base_set(payload, mid_base);
}

/* SFDF - Switch Filtering DB Flush
 * --------------------------------
 * The switch filtering DB flush register is used to flush the FDB.
 * Note that FDB notifications are flushed as well.
 */

#define MLXSW_REG_SFDF_ID 0x2013
#define MLXSW_REG_SFDF_LEN 0x14

MLXSW_REG_DEFINE(sfdf, MLXSW_REG_SFDF_ID, MLXSW_REG_SFDF_LEN);

/* reg_sfdf_swid
 * Switch partition ID.
 * Access: Index
 */

MLXSW_ITEM32(reg, sfdf, swid, 0x00, 24, 8);

enum mlxsw_reg_sfdf_flush_type {
 MLXSW_REG_SFDF_FLUSH_PER_SWID,
 MLXSW_REG_SFDF_FLUSH_PER_FID,
 MLXSW_REG_SFDF_FLUSH_PER_PORT,
 MLXSW_REG_SFDF_FLUSH_PER_PORT_AND_FID,
 MLXSW_REG_SFDF_FLUSH_PER_LAG,
 MLXSW_REG_SFDF_FLUSH_PER_LAG_AND_FID,
 MLXSW_REG_SFDF_FLUSH_PER_NVE,
 MLXSW_REG_SFDF_FLUSH_PER_NVE_AND_FID,
};

/* reg_sfdf_flush_type
 * Flush type.
 * 0 - All SWID dynamic entries are flushed.
 * 1 - All FID dynamic entries are flushed.
 * 2 - All dynamic entries pointing to port are flushed.
 * 3 - All FID dynamic entries pointing to port are flushed.
 * 4 - All dynamic entries pointing to LAG are flushed.
 * 5 - All FID dynamic entries pointing to LAG are flushed.
 * 6 - All entries of type "Unicast Tunnel" or "Multicast Tunnel" are
 *     flushed.
 * 7 - All entries of type "Unicast Tunnel" or "Multicast Tunnel" are
 *     flushed, per FID.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfdf, flush_type, 0x04, 28, 4);

/* reg_sfdf_flush_static
 * Static.
 * 0 - Flush only dynamic entries.
 * 1 - Flush both dynamic and static entries.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfdf, flush_static, 0x04, 24, 1);

static inline void mlxsw_reg_sfdf_pack(char *payload,
           enum mlxsw_reg_sfdf_flush_type type)
{
 MLXSW_REG_ZERO(sfdf, payload);
 mlxsw_reg_sfdf_flush_type_set(payload, type);
 mlxsw_reg_sfdf_flush_static_set(payload, true);
}

/* reg_sfdf_fid
 * FID to flush.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfdf, fid, 0x0C, 0, 16);

/* reg_sfdf_system_port
 * Port to flush.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfdf, system_port, 0x0C, 0, 16);

/* reg_sfdf_port_fid_system_port
 * Port to flush, pointed to by FID.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfdf, port_fid_system_port, 0x08, 0, 16);

/* reg_sfdf_lag_id
 * LAG ID to flush.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfdf, lag_id, 0x0C, 0, 10);

/* reg_sfdf_lag_fid_lag_id
 * LAG ID to flush, pointed to by FID.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfdf, lag_fid_lag_id, 0x08, 0, 10);

/* SLDR - Switch LAG Descriptor Register
 * -----------------------------------------
 * The switch LAG descriptor register is populated by LAG descriptors.
 * Each LAG descriptor is indexed by lag_id. The LAG ID runs from 0 to
 * max_lag-1.
 */

#define MLXSW_REG_SLDR_ID 0x2014
#define MLXSW_REG_SLDR_LEN 0x0C /* counting in only one port in list */

MLXSW_REG_DEFINE(sldr, MLXSW_REG_SLDR_ID, MLXSW_REG_SLDR_LEN);

enum mlxsw_reg_sldr_op {
 /* Indicates a creation of a new LAG-ID, lag_id must be valid */
 MLXSW_REG_SLDR_OP_LAG_CREATE,
 MLXSW_REG_SLDR_OP_LAG_DESTROY,
 /* Ports that appear in the list have the Distributor enabled */
 MLXSW_REG_SLDR_OP_LAG_ADD_PORT_LIST,
 /* Removes ports from the disributor list */
 MLXSW_REG_SLDR_OP_LAG_REMOVE_PORT_LIST,
};

/* reg_sldr_op
 * Operation.
 * Access: RW
 */

MLXSW_ITEM32(reg, sldr, op, 0x00, 29, 3);

/* reg_sldr_lag_id
 * LAG identifier. The lag_id is the index into the LAG descriptor table.
 * Access: Index
 */

MLXSW_ITEM32(reg, sldr, lag_id, 0x00, 0, 10);

static inline void mlxsw_reg_sldr_lag_create_pack(char *payload, u8 lag_id)
{
 MLXSW_REG_ZERO(sldr, payload);
 mlxsw_reg_sldr_op_set(payload, MLXSW_REG_SLDR_OP_LAG_CREATE);
 mlxsw_reg_sldr_lag_id_set(payload, lag_id);
}

static inline void mlxsw_reg_sldr_lag_destroy_pack(char *payload, u8 lag_id)
{
 MLXSW_REG_ZERO(sldr, payload);
 mlxsw_reg_sldr_op_set(payload, MLXSW_REG_SLDR_OP_LAG_DESTROY);
 mlxsw_reg_sldr_lag_id_set(payload, lag_id);
}

/* reg_sldr_num_ports
 * The number of member ports of the LAG.
 * Reserved for Create / Destroy operations
 * For Add / Remove operations - indicates the number of ports in the list.
 * Access: RW
 */

MLXSW_ITEM32(reg, sldr, num_ports, 0x04, 24, 8);

/* reg_sldr_system_port
 * System port.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, sldr, system_port, 0x08, 0, 16, 4, 0, false);

static inline void mlxsw_reg_sldr_lag_add_port_pack(char *payload, u8 lag_id,
          u16 local_port)
{
 MLXSW_REG_ZERO(sldr, payload);
 mlxsw_reg_sldr_op_set(payload, MLXSW_REG_SLDR_OP_LAG_ADD_PORT_LIST);
 mlxsw_reg_sldr_lag_id_set(payload, lag_id);
 mlxsw_reg_sldr_num_ports_set(payload, 1);
 mlxsw_reg_sldr_system_port_set(payload, 0, local_port);
}

static inline void mlxsw_reg_sldr_lag_remove_port_pack(char *payload, u8 lag_id,
             u16 local_port)
{
 MLXSW_REG_ZERO(sldr, payload);
 mlxsw_reg_sldr_op_set(payload, MLXSW_REG_SLDR_OP_LAG_REMOVE_PORT_LIST);
 mlxsw_reg_sldr_lag_id_set(payload, lag_id);
 mlxsw_reg_sldr_num_ports_set(payload, 1);
 mlxsw_reg_sldr_system_port_set(payload, 0, local_port);
}

/* SLCR - Switch LAG Configuration 2 Register
 * -------------------------------------------
 * The Switch LAG Configuration register is used for configuring the
 * LAG properties of the switch.
 */

#define MLXSW_REG_SLCR_ID 0x2015
#define MLXSW_REG_SLCR_LEN 0x10

MLXSW_REG_DEFINE(slcr, MLXSW_REG_SLCR_ID, MLXSW_REG_SLCR_LEN);

enum mlxsw_reg_slcr_pp {
 /* Global Configuration (for all ports) */
 MLXSW_REG_SLCR_PP_GLOBAL,
 /* Per port configuration, based on local_port field */
 MLXSW_REG_SLCR_PP_PER_PORT,
};

/* reg_slcr_pp
 * Per Port Configuration
 * Note: Reading at Global mode results in reading port 1 configuration.
 * Access: Index
 */

MLXSW_ITEM32(reg, slcr, pp, 0x00, 24, 1);

/* reg_slcr_local_port
 * Local port number
 * Supported from CPU port
 * Not supported from router port
 * Reserved when pp = Global Configuration
 * Access: Index
 */

MLXSW_ITEM32_LP(reg, slcr, 0x00, 16, 0x00, 12);

enum mlxsw_reg_slcr_type {
 MLXSW_REG_SLCR_TYPE_CRC, /* default */
 MLXSW_REG_SLCR_TYPE_XOR,
 MLXSW_REG_SLCR_TYPE_RANDOM,
};

/* reg_slcr_type
 * Hash type
 * Access: RW
 */

MLXSW_ITEM32(reg, slcr, type, 0x00, 0, 4);

/* Ingress port */
#define MLXSW_REG_SLCR_LAG_HASH_IN_PORT  BIT(0)
/* SMAC - for IPv4 and IPv6 packets */
#define MLXSW_REG_SLCR_LAG_HASH_SMAC_IP  BIT(1)
/* SMAC - for non-IP packets */
#define MLXSW_REG_SLCR_LAG_HASH_SMAC_NONIP BIT(2)
#define MLXSW_REG_SLCR_LAG_HASH_SMAC \
 (MLXSW_REG_SLCR_LAG_HASH_SMAC_IP | \
  MLXSW_REG_SLCR_LAG_HASH_SMAC_NONIP)
/* DMAC - for IPv4 and IPv6 packets */
#define MLXSW_REG_SLCR_LAG_HASH_DMAC_IP  BIT(3)
/* DMAC - for non-IP packets */
#define MLXSW_REG_SLCR_LAG_HASH_DMAC_NONIP BIT(4)
#define MLXSW_REG_SLCR_LAG_HASH_DMAC \
 (MLXSW_REG_SLCR_LAG_HASH_DMAC_IP | \
  MLXSW_REG_SLCR_LAG_HASH_DMAC_NONIP)
/* Ethertype - for IPv4 and IPv6 packets */
#define MLXSW_REG_SLCR_LAG_HASH_ETHERTYPE_IP BIT(5)
/* Ethertype - for non-IP packets */
#define MLXSW_REG_SLCR_LAG_HASH_ETHERTYPE_NONIP BIT(6)
#define MLXSW_REG_SLCR_LAG_HASH_ETHERTYPE \
 (MLXSW_REG_SLCR_LAG_HASH_ETHERTYPE_IP | \
  MLXSW_REG_SLCR_LAG_HASH_ETHERTYPE_NONIP)
/* VLAN ID - for IPv4 and IPv6 packets */
#define MLXSW_REG_SLCR_LAG_HASH_VLANID_IP BIT(7)
/* VLAN ID - for non-IP packets */
#define MLXSW_REG_SLCR_LAG_HASH_VLANID_NONIP BIT(8)
#define MLXSW_REG_SLCR_LAG_HASH_VLANID \
 (MLXSW_REG_SLCR_LAG_HASH_VLANID_IP | \
  MLXSW_REG_SLCR_LAG_HASH_VLANID_NONIP)
/* Source IP address (can be IPv4 or IPv6) */
#define MLXSW_REG_SLCR_LAG_HASH_SIP  BIT(9)
/* Destination IP address (can be IPv4 or IPv6) */
#define MLXSW_REG_SLCR_LAG_HASH_DIP  BIT(10)
/* TCP/UDP source port */
#define MLXSW_REG_SLCR_LAG_HASH_SPORT  BIT(11)
/* TCP/UDP destination port*/
#define MLXSW_REG_SLCR_LAG_HASH_DPORT  BIT(12)
/* IPv4 Protocol/IPv6 Next Header */
#define MLXSW_REG_SLCR_LAG_HASH_IPPROTO  BIT(13)
/* IPv6 Flow label */
#define MLXSW_REG_SLCR_LAG_HASH_FLOWLABEL BIT(14)
/* SID - FCoE source ID */
#define MLXSW_REG_SLCR_LAG_HASH_FCOE_SID BIT(15)
/* DID - FCoE destination ID */
#define MLXSW_REG_SLCR_LAG_HASH_FCOE_DID BIT(16)
/* OXID - FCoE originator exchange ID */
#define MLXSW_REG_SLCR_LAG_HASH_FCOE_OXID BIT(17)
/* Destination QP number - for RoCE packets */
#define MLXSW_REG_SLCR_LAG_HASH_ROCE_DQP BIT(19)

/* reg_slcr_lag_hash
 * LAG hashing configuration. This is a bitmask, in which each set
 * bit includes the corresponding item in the LAG hash calculation.
 * The default lag_hash contains SMAC, DMAC, VLANID and
 * Ethertype (for all packet types).
 * Access: RW
 */

MLXSW_ITEM32(reg, slcr, lag_hash, 0x04, 0, 20);

/* reg_slcr_seed
 * LAG seed value. The seed is the same for all ports.
 * Access: RW
 */

MLXSW_ITEM32(reg, slcr, seed, 0x08, 0, 32);

static inline void mlxsw_reg_slcr_pack(char *payload, u16 lag_hash, u32 seed)
{
 MLXSW_REG_ZERO(slcr, payload);
 mlxsw_reg_slcr_pp_set(payload, MLXSW_REG_SLCR_PP_GLOBAL);
 mlxsw_reg_slcr_type_set(payload, MLXSW_REG_SLCR_TYPE_CRC);
 mlxsw_reg_slcr_lag_hash_set(payload, lag_hash);
 mlxsw_reg_slcr_seed_set(payload, seed);
}

/* SLCOR - Switch LAG Collector Register
 * -------------------------------------
 * The Switch LAG Collector register controls the Local Port membership
 * in a LAG and enablement of the collector.
 */

#define MLXSW_REG_SLCOR_ID 0x2016
#define MLXSW_REG_SLCOR_LEN 0x10

MLXSW_REG_DEFINE(slcor, MLXSW_REG_SLCOR_ID, MLXSW_REG_SLCOR_LEN);

enum mlxsw_reg_slcor_col {
 /* Port is added with collector disabled */
 MLXSW_REG_SLCOR_COL_LAG_ADD_PORT,
 MLXSW_REG_SLCOR_COL_LAG_COLLECTOR_ENABLED,
 MLXSW_REG_SLCOR_COL_LAG_COLLECTOR_DISABLED,
 MLXSW_REG_SLCOR_COL_LAG_REMOVE_PORT,
};

/* reg_slcor_col
 * Collector configuration
 * Access: RW
 */

MLXSW_ITEM32(reg, slcor, col, 0x00, 30, 2);

/* reg_slcor_local_port
 * Local port number
 * Not supported for CPU port
 * Access: Index
 */

MLXSW_ITEM32_LP(reg, slcor, 0x00, 16, 0x00, 12);

/* reg_slcor_lag_id
 * LAG Identifier. Index into the LAG descriptor table.
 * Access: Index
 */

MLXSW_ITEM32(reg, slcor, lag_id, 0x00, 0, 10);

/* reg_slcor_port_index
 * Port index in the LAG list. Only valid on Add Port to LAG col.
 * Valid range is from 0 to cap_max_lag_members-1
 * Access: RW
 */

MLXSW_ITEM32(reg, slcor, port_index, 0x04, 0, 10);

static inline void mlxsw_reg_slcor_pack(char *payload,
     u16 local_port, u16 lag_id,
     enum mlxsw_reg_slcor_col col)
{
 MLXSW_REG_ZERO(slcor, payload);
 mlxsw_reg_slcor_col_set(payload, col);
 mlxsw_reg_slcor_local_port_set(payload, local_port);
 mlxsw_reg_slcor_lag_id_set(payload, lag_id);
}

static inline void mlxsw_reg_slcor_port_add_pack(char *payload,
       u16 local_port, u16 lag_id,
       u8 port_index)
{
 mlxsw_reg_slcor_pack(payload, local_port, lag_id,
        MLXSW_REG_SLCOR_COL_LAG_ADD_PORT);
 mlxsw_reg_slcor_port_index_set(payload, port_index);
}

static inline void mlxsw_reg_slcor_port_remove_pack(char *payload,
          u16 local_port, u16 lag_id)
{
 mlxsw_reg_slcor_pack(payload, local_port, lag_id,
        MLXSW_REG_SLCOR_COL_LAG_REMOVE_PORT);
}

static inline void mlxsw_reg_slcor_col_enable_pack(char *payload,
         u16 local_port, u16 lag_id)
{
 mlxsw_reg_slcor_pack(payload, local_port, lag_id,
        MLXSW_REG_SLCOR_COL_LAG_COLLECTOR_ENABLED);
}

static inline void mlxsw_reg_slcor_col_disable_pack(char *payload,
          u16 local_port, u16 lag_id)
{
 mlxsw_reg_slcor_pack(payload, local_port, lag_id,
        MLXSW_REG_SLCOR_COL_LAG_COLLECTOR_ENABLED);
}

/* SPMLR - Switch Port MAC Learning Register
 * -----------------------------------------
 * Controls the Switch MAC learning policy per port.
 */

#define MLXSW_REG_SPMLR_ID 0x2018
#define MLXSW_REG_SPMLR_LEN 0x8

MLXSW_REG_DEFINE(spmlr, MLXSW_REG_SPMLR_ID, MLXSW_REG_SPMLR_LEN);

/* reg_spmlr_local_port
 * Local port number.
 * Access: Index
 */

MLXSW_ITEM32_LP(reg, spmlr, 0x00, 16, 0x00, 12);

/* reg_spmlr_sub_port
 * Virtual port within the physical port.
 * Should be set to 0 when virtual ports are not enabled on the port.
 * Access: Index
 */

MLXSW_ITEM32(reg, spmlr, sub_port, 0x00, 8, 8);

enum mlxsw_reg_spmlr_learn_mode {
 MLXSW_REG_SPMLR_LEARN_MODE_DISABLE = 0,
 MLXSW_REG_SPMLR_LEARN_MODE_ENABLE = 2,
 MLXSW_REG_SPMLR_LEARN_MODE_SEC = 3,
};

/* reg_spmlr_learn_mode
 * Learning mode on the port.
 * 0 - Learning disabled.
 * 2 - Learning enabled.
 * 3 - Security mode.
 *
 * In security mode the switch does not learn MACs on the port, but uses the
 * SMAC to see if it exists on another ingress port. If so, the packet is
 * classified as a bad packet and is discarded unless the software registers
 * to receive port security error packets usign HPKT.
 */

MLXSW_ITEM32(reg, spmlr, learn_mode, 0x04, 30, 2);

static inline void mlxsw_reg_spmlr_pack(char *payload, u16 local_port,
     enum mlxsw_reg_spmlr_learn_mode mode)
{
 MLXSW_REG_ZERO(spmlr, payload);
 mlxsw_reg_spmlr_local_port_set(payload, local_port);
 mlxsw_reg_spmlr_sub_port_set(payload, 0);
 mlxsw_reg_spmlr_learn_mode_set(payload, mode);
}

/* SVFA - Switch VID to FID Allocation Register
 * --------------------------------------------
 * Controls the VID to FID mapping and {Port, VID} to FID mapping for
 * virtualized ports.
 */

#define MLXSW_REG_SVFA_ID 0x201C
#define MLXSW_REG_SVFA_LEN 0x18

MLXSW_REG_DEFINE(svfa, MLXSW_REG_SVFA_ID, MLXSW_REG_SVFA_LEN);

/* reg_svfa_swid
 * Switch partition ID.
 * Access: Index
 */

MLXSW_ITEM32(reg, svfa, swid, 0x00, 24, 8);

/* reg_svfa_local_port
 * Local port number.
 * Access: Index
 *
 * Note: Reserved for 802.1Q FIDs.
 */

MLXSW_ITEM32_LP(reg, svfa, 0x00, 16, 0x00, 12);

enum mlxsw_reg_svfa_mt {
 MLXSW_REG_SVFA_MT_VID_TO_FID,
 MLXSW_REG_SVFA_MT_PORT_VID_TO_FID,
 MLXSW_REG_SVFA_MT_VNI_TO_FID,
};

/* reg_svfa_mapping_table
 * Mapping table:
 * 0 - VID to FID
 * 1 - {Port, VID} to FID
 * Access: Index
 *
 * Note: Reserved for SwitchX-2.
 */

MLXSW_ITEM32(reg, svfa, mapping_table, 0x00, 8, 3);

/* reg_svfa_v
 * Valid.
 * Valid if set.
 * Access: RW
 *
 * Note: Reserved for SwitchX-2.
 */

MLXSW_ITEM32(reg, svfa, v, 0x00, 0, 1);

/* reg_svfa_fid
 * Filtering ID.
 * Access: RW
 */

MLXSW_ITEM32(reg, svfa, fid, 0x04, 16, 16);

/* reg_svfa_vid
 * VLAN ID.
 * Access: Index
 */

MLXSW_ITEM32(reg, svfa, vid, 0x04, 0, 12);

/* reg_svfa_counter_set_type
 * Counter set type for flow counters.
 * Access: RW
 *
 * Note: Reserved for SwitchX-2.
 */

MLXSW_ITEM32(reg, svfa, counter_set_type, 0x08, 24, 8);

/* reg_svfa_counter_index
 * Counter index for flow counters.
 * Access: RW
 *
 * Note: Reserved for SwitchX-2.
 */

MLXSW_ITEM32(reg, svfa, counter_index, 0x08, 0, 24);

/* reg_svfa_vni
 * Virtual Network Identifier.
 * Access: Index
 *
 * Note: Reserved when mapping_table is not 2 (VNI mapping table).
 */

MLXSW_ITEM32(reg, svfa, vni, 0x10, 0, 24);

/* reg_svfa_irif_v
 * Ingress RIF valid.
 * 0 - Ingress RIF is not valid, no ingress RIF assigned.
 * 1 - Ingress RIF valid.
 * Must not be set for a non enabled RIF.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used.
 */

MLXSW_ITEM32(reg, svfa, irif_v, 0x14, 24, 1);

/* reg_svfa_irif
 * Ingress RIF (Router Interface).
 * Range is 0..cap_max_router_interfaces-1.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used and when irif_v=0.
 */

MLXSW_ITEM32(reg, svfa, irif, 0x14, 0, 16);

static inline void __mlxsw_reg_svfa_pack(char *payload,
      enum mlxsw_reg_svfa_mt mt, bool valid,
      u16 fid, bool irif_v, u16 irif)
{
 MLXSW_REG_ZERO(svfa, payload);
 mlxsw_reg_svfa_swid_set(payload, 0);
 mlxsw_reg_svfa_mapping_table_set(payload, mt);
 mlxsw_reg_svfa_v_set(payload, valid);
 mlxsw_reg_svfa_fid_set(payload, fid);
 mlxsw_reg_svfa_irif_v_set(payload, irif_v);
 mlxsw_reg_svfa_irif_set(payload, irif_v ? irif : 0);
}

static inline void mlxsw_reg_svfa_port_vid_pack(char *payload, u16 local_port,
      bool valid, u16 fid, u16 vid,
      bool irif_v, u16 irif)
{
 enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;

 __mlxsw_reg_svfa_pack(payload, mt, valid, fid, irif_v, irif);
 mlxsw_reg_svfa_local_port_set(payload, local_port);
 mlxsw_reg_svfa_vid_set(payload, vid);
}

static inline void mlxsw_reg_svfa_vid_pack(char *payload, bool valid, u16 fid,
        u16 vid, bool irif_v, u16 irif)
{
 enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_VID_TO_FID;

 __mlxsw_reg_svfa_pack(payload, mt, valid, fid, irif_v, irif);
 mlxsw_reg_svfa_vid_set(payload, vid);
}

static inline void mlxsw_reg_svfa_vni_pack(char *payload, bool valid, u16 fid,
        u32 vni, bool irif_v, u16 irif)
{
 enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_VNI_TO_FID;

 __mlxsw_reg_svfa_pack(payload, mt, valid, fid, irif_v, irif);
 mlxsw_reg_svfa_vni_set(payload, vni);
}

/*  SPVTR - Switch Port VLAN Stacking Register
 *  ------------------------------------------
 *  The Switch Port VLAN Stacking register configures the VLAN mode of the port
 *  to enable VLAN stacking.
 */

#define MLXSW_REG_SPVTR_ID 0x201D
#define MLXSW_REG_SPVTR_LEN 0x10

MLXSW_REG_DEFINE(spvtr, MLXSW_REG_SPVTR_ID, MLXSW_REG_SPVTR_LEN);

/* reg_spvtr_tport
 * Port is tunnel port.
 * Access: Index
 *
 * Note: Reserved when SwitchX/-2 or Spectrum-1.
 */

MLXSW_ITEM32(reg, spvtr, tport, 0x00, 24, 1);

/* reg_spvtr_local_port
 * When tport = 0: local port number (Not supported from/to CPU).
 * When tport = 1: tunnel port.
 * Access: Index
 */

MLXSW_ITEM32_LP(reg, spvtr, 0x00, 16, 0x00, 12);

/* reg_spvtr_ippe
 * Ingress Port Prio Mode Update Enable.
 * When set, the Port Prio Mode is updated with the provided ipprio_mode field.
 * Reserved on Get operations.
 * Access: OP
 */

MLXSW_ITEM32(reg, spvtr, ippe, 0x04, 31, 1);

/* reg_spvtr_ipve
 * Ingress Port VID Mode Update Enable.
 * When set, the Ingress Port VID Mode is updated with the provided ipvid_mode
 * field.
 * Reserved on Get operations.
 * Access: OP
 */

MLXSW_ITEM32(reg, spvtr, ipve, 0x04, 30, 1);

/* reg_spvtr_epve
 * Egress Port VID Mode Update Enable.
 * When set, the Egress Port VID Mode is updated with the provided epvid_mode
 * field.
 * Access: OP
 */

MLXSW_ITEM32(reg, spvtr, epve, 0x04, 29, 1);

/* reg_spvtr_ipprio_mode
 * Ingress Port Priority Mode.
 * This controls the PCP and DEI of the new outer VLAN
 * Note: for SwitchX/-2 the DEI is not affected.
 * 0: use port default PCP and DEI (configured by QPDPC).
 * 1: use C-VLAN PCP and DEI.
 * Has no effect when ipvid_mode = 0.
 * Reserved when tport = 1.
 * Access: RW
 */

MLXSW_ITEM32(reg, spvtr, ipprio_mode, 0x04, 20, 4);

enum mlxsw_reg_spvtr_ipvid_mode {
 /* IEEE Compliant PVID (default) */
 MLXSW_REG_SPVTR_IPVID_MODE_IEEE_COMPLIANT_PVID,
 /* Push VLAN (for VLAN stacking, except prio tagged packets) */
 MLXSW_REG_SPVTR_IPVID_MODE_PUSH_VLAN_FOR_UNTAGGED_PACKET,
 /* Always push VLAN (also for prio tagged packets) */
 MLXSW_REG_SPVTR_IPVID_MODE_ALWAYS_PUSH_VLAN,
};

/* reg_spvtr_ipvid_mode
 * Ingress Port VLAN-ID Mode.
 * For Spectrum family, this affects the values of SPVM.i
 * Access: RW
 */

MLXSW_ITEM32(reg, spvtr, ipvid_mode, 0x04, 16, 4);

enum mlxsw_reg_spvtr_epvid_mode {
 /* IEEE Compliant VLAN membership */
 MLXSW_REG_SPVTR_EPVID_MODE_IEEE_COMPLIANT_VLAN_MEMBERSHIP,
 /* Pop VLAN (for VLAN stacking) */
 MLXSW_REG_SPVTR_EPVID_MODE_POP_VLAN,
};

/* reg_spvtr_epvid_mode
 * Egress Port VLAN-ID Mode.
 * For Spectrum family, this affects the values of SPVM.e,u,pt.
 * Access: WO
 */

MLXSW_ITEM32(reg, spvtr, epvid_mode, 0x04, 0, 4);

static inline void mlxsw_reg_spvtr_pack(char *payload, bool tport,
     u16 local_port,
     enum mlxsw_reg_spvtr_ipvid_mode ipvid_mode)
{
 MLXSW_REG_ZERO(spvtr, payload);
 mlxsw_reg_spvtr_tport_set(payload, tport);
 mlxsw_reg_spvtr_local_port_set(payload, local_port);
 mlxsw_reg_spvtr_ipvid_mode_set(payload, ipvid_mode);
 mlxsw_reg_spvtr_ipve_set(payload, true);
}

/* SVPE - Switch Virtual-Port Enabling Register
 * --------------------------------------------
 * Enables port virtualization.
 */

#define MLXSW_REG_SVPE_ID 0x201E
#define MLXSW_REG_SVPE_LEN 0x4

MLXSW_REG_DEFINE(svpe, MLXSW_REG_SVPE_ID, MLXSW_REG_SVPE_LEN);

/* reg_svpe_local_port
 * Local port number
 * Access: Index
 *
 * Note: CPU port is not supported (uses VLAN mode only).
 */

MLXSW_ITEM32_LP(reg, svpe, 0x00, 16, 0x00, 12);

/* reg_svpe_vp_en
 * Virtual port enable.
 * 0 - Disable, VLAN mode (VID to FID).
 * 1 - Enable, Virtual port mode ({Port, VID} to FID).
 * Access: RW
 */

MLXSW_ITEM32(reg, svpe, vp_en, 0x00, 8, 1);

static inline void mlxsw_reg_svpe_pack(char *payload, u16 local_port,
           bool enable)
{
 MLXSW_REG_ZERO(svpe, payload);
 mlxsw_reg_svpe_local_port_set(payload, local_port);
 mlxsw_reg_svpe_vp_en_set(payload, enable);
}

/* SFMR - Switch FID Management Register
 * -------------------------------------
 * Creates and configures FIDs.
 */

#define MLXSW_REG_SFMR_ID 0x201F
#define MLXSW_REG_SFMR_LEN 0x30

MLXSW_REG_DEFINE(sfmr, MLXSW_REG_SFMR_ID, MLXSW_REG_SFMR_LEN);

enum mlxsw_reg_sfmr_op {
 MLXSW_REG_SFMR_OP_CREATE_FID,
 MLXSW_REG_SFMR_OP_DESTROY_FID,
};

/* reg_sfmr_op
 * Operation.
 * 0 - Create or edit FID.
 * 1 - Destroy FID.
 * Access: WO
 */

MLXSW_ITEM32(reg, sfmr, op, 0x00, 24, 4);

/* reg_sfmr_fid
 * Filtering ID.
 * Access: Index
 */

MLXSW_ITEM32(reg, sfmr, fid, 0x00, 0, 16);

/* reg_sfmr_flood_rsp
 * Router sub-port flooding table.
 * 0 - Regular flooding table.
 * 1 - Router sub-port flooding table. For this FID the flooding is per
 * router-sub-port local_port. Must not be set for a FID which is not a
 * router-sub-port and must be set prior to enabling the relevant RIF.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used.
 * Reserved when CONFIG_PROFILE.flood_mode = CFF.
 */

MLXSW_ITEM32(reg, sfmr, flood_rsp, 0x08, 31, 1);

/* reg_sfmr_flood_bridge_type
 * Flood bridge type (see SFGC.bridge_type).
 * 0 - type_0.
 * 1 - type_1.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used and when flood_rsp=1.
 * Reserved when CONFIG_PROFILE.flood_mode = CFF
 */

MLXSW_ITEM32(reg, sfmr, flood_bridge_type, 0x08, 28, 1);

/* reg_sfmr_fid_offset
 * FID offset.
 * Used to point into the flooding table selected by SFGC register if
 * the table is of type FID-Offset. Otherwise, this field is reserved.
 * Access: RW
 *
 * Note: Reserved when CONFIG_PROFILE.flood_mode = CFF
 */

MLXSW_ITEM32(reg, sfmr, fid_offset, 0x08, 0, 16);

/* reg_sfmr_vtfp
 * Valid Tunnel Flood Pointer.
 * If not set, then nve_tunnel_flood_ptr is reserved and considered NULL.
 * Access: RW
 *
 * Note: Reserved for 802.1Q FIDs.
 */

MLXSW_ITEM32(reg, sfmr, vtfp, 0x0C, 31, 1);

/* reg_sfmr_nve_tunnel_flood_ptr
 * Underlay Flooding and BC Pointer.
 * Used as a pointer to the first entry of the group based link lists of
 * flooding or BC entries (for NVE tunnels).
 * Access: RW
 */

MLXSW_ITEM32(reg, sfmr, nve_tunnel_flood_ptr, 0x0C, 0, 24);

/* reg_sfmr_vv
 * VNI Valid.
 * If not set, then vni is reserved.
 * Access: RW
 *
 * Note: Reserved for 802.1Q FIDs.
 */

MLXSW_ITEM32(reg, sfmr, vv, 0x10, 31, 1);

/* reg_sfmr_vni
 * Virtual Network Identifier.
 * When legacy bridge model is used, a given VNI can only be assigned to one
 * FID. When unified bridge model is used, it configures only the FID->VNI,
 * the VNI->FID is done by SVFA.
 * Access: RW
 */

MLXSW_ITEM32(reg, sfmr, vni, 0x10, 0, 24);

/* reg_sfmr_irif_v
 * Ingress RIF valid.
 * 0 - Ingress RIF is not valid, no ingress RIF assigned.
 * 1 - Ingress RIF valid.
 * Must not be set for a non valid RIF.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used.
 */

MLXSW_ITEM32(reg, sfmr, irif_v, 0x14, 24, 1);

/* reg_sfmr_irif
 * Ingress RIF (Router Interface).
 * Range is 0..cap_max_router_interfaces-1.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used and when irif_v=0.
 */

MLXSW_ITEM32(reg, sfmr, irif, 0x14, 0, 16);

/* reg_sfmr_cff_mid_base
 * Pointer to PGT table.
 * Range: 0..(cap_max_pgt-1)
 * Access: RW
 *
 * Note: Reserved when SwitchX/-2 and Spectrum-1.
 * Supported when CONFIG_PROFILE.flood_mode = CFF.
 */

MLXSW_ITEM32(reg, sfmr, cff_mid_base, 0x20, 0, 16);

/* reg_sfmr_nve_flood_prf_id
 * FID flooding profile_id for NVE Encap
 * Range 0..(max_cap_nve_flood_prf-1)
 * Access: RW
 *
 * Note: Reserved when SwitchX/-2 and Spectrum-1
 */

MLXSW_ITEM32(reg, sfmr, nve_flood_prf_id, 0x24, 8, 2);

/* reg_sfmr_cff_prf_id
 * Compressed Fid Flooding profile_id
 * Range 0..(max_cap_nve_flood_prf-1)
 * Access: RW
 *
 * Note: Reserved when SwitchX/-2 and Spectrum-1
 * Supported only when CONFIG_PROFLE.flood_mode = CFF.
 */

MLXSW_ITEM32(reg, sfmr, cff_prf_id, 0x24, 0, 2);

/* reg_sfmr_smpe_valid
 * SMPE is valid.
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used, when flood_rsp=1 and on
 * Spectrum-1.
 */

MLXSW_ITEM32(reg, sfmr, smpe_valid, 0x28, 20, 1);

/* reg_sfmr_smpe
 * Switch multicast port to egress VID.
 * Range is 0..cap_max_rmpe-1
 * Access: RW
 *
 * Note: Reserved when legacy bridge model is used, when flood_rsp=1 and on
 * Spectrum-1.
 */

MLXSW_ITEM32(reg, sfmr, smpe, 0x28, 0, 16);

static inline void mlxsw_reg_sfmr_pack(char *payload,
           enum mlxsw_reg_sfmr_op op, u16 fid,
           bool smpe_valid, u16 smpe)
{
 MLXSW_REG_ZERO(sfmr, payload);
 mlxsw_reg_sfmr_op_set(payload, op);
 mlxsw_reg_sfmr_fid_set(payload, fid);
 mlxsw_reg_sfmr_smpe_valid_set(payload, smpe_valid);
 mlxsw_reg_sfmr_smpe_set(payload, smpe);
}

/* SPVMLR - Switch Port VLAN MAC Learning Register
 * -----------------------------------------------
 * Controls the switch MAC learning policy per {Port, VID}.
 */

#define MLXSW_REG_SPVMLR_ID 0x2020
#define MLXSW_REG_SPVMLR_BASE_LEN 0x04 /* base length, without records */
#define MLXSW_REG_SPVMLR_REC_LEN 0x04 /* record length */
#define MLXSW_REG_SPVMLR_REC_MAX_COUNT 255
#define MLXSW_REG_SPVMLR_LEN (MLXSW_REG_SPVMLR_BASE_LEN + \
         MLXSW_REG_SPVMLR_REC_LEN * \
         MLXSW_REG_SPVMLR_REC_MAX_COUNT)

MLXSW_REG_DEFINE(spvmlr, MLXSW_REG_SPVMLR_ID, MLXSW_REG_SPVMLR_LEN);

/* reg_spvmlr_local_port
 * Local ingress port.
 * Access: Index
 *
 * Note: CPU port is not supported.
 */

MLXSW_ITEM32_LP(reg, spvmlr, 0x00, 16, 0x00, 12);

/* reg_spvmlr_num_rec
 * Number of records to update.
 * Access: OP
 */

MLXSW_ITEM32(reg, spvmlr, num_rec, 0x00, 0, 8);

/* reg_spvmlr_rec_learn_enable
 * 0 - Disable learning for {Port, VID}.
 * 1 - Enable learning for {Port, VID}.
 * Access: RW
 */

MLXSW_ITEM32_INDEXED(reg, spvmlr, rec_learn_enable, MLXSW_REG_SPVMLR_BASE_LEN,
       31, 1, MLXSW_REG_SPVMLR_REC_LEN, 0x00, false);

/* reg_spvmlr_rec_vid
 * VLAN ID to be added/removed from port or for querying.
 * Access: Index
 */

MLXSW_ITEM32_INDEXED(reg, spvmlr, rec_vid, MLXSW_REG_SPVMLR_BASE_LEN, 0, 12,
       MLXSW_REG_SPVMLR_REC_LEN, 0x00, false);

static inline void mlxsw_reg_spvmlr_pack(char *payload, u16 local_port,
      u16 vid_begin, u16 vid_end,
      bool learn_enable)
{
 int num_rec = vid_end - vid_begin + 1;
 int i;

 WARN_ON(num_rec < 1 || num_rec > MLXSW_REG_SPVMLR_REC_MAX_COUNT);

 MLXSW_REG_ZERO(spvmlr, payload);
 mlxsw_reg_spvmlr_local_port_set(payload, local_port);
 mlxsw_reg_spvmlr_num_rec_set(payload, num_rec);

 for (i = 0; i < num_rec; i++) {
  mlxsw_reg_spvmlr_rec_learn_enable_set(payload, i, learn_enable);
  mlxsw_reg_spvmlr_rec_vid_set(payload, i, vid_begin + i);
 }
}

/* SPFSR - Switch Port FDB Security Register
 * -----------------------------------------
 * Configures the security mode per port.
 */

#define MLXSW_REG_SPFSR_ID 0x2023
#define MLXSW_REG_SPFSR_LEN 0x08

MLXSW_REG_DEFINE(spfsr, MLXSW_REG_SPFSR_ID, MLXSW_REG_SPFSR_LEN);

/* reg_spfsr_local_port
 * Local port.
 * Access: Index
 *
 * Note: not supported for CPU port.
 */

MLXSW_ITEM32_LP(reg, spfsr, 0x00, 16, 0x00, 12);

/* reg_spfsr_security
 * Security checks.
 * 0: disabled (default)
 * 1: enabled
 * Access: RW
 */

MLXSW_ITEM32(reg, spfsr, security, 0x04, 31, 1);

static inline void mlxsw_reg_spfsr_pack(char *payload, u16 local_port,
     bool security)
{
 MLXSW_REG_ZERO(spfsr, payload);
 mlxsw_reg_spfsr_local_port_set(payload, local_port);
 mlxsw_reg_spfsr_security_set(payload, security);
}

/* SPVC - Switch Port VLAN Classification Register
 * -----------------------------------------------
 * Configures the port to identify packets as untagged / single tagged /
 * double packets based on the packet EtherTypes.
 * Ethertype IDs are configured by SVER.
 */

#define MLXSW_REG_SPVC_ID 0x2026
#define MLXSW_REG_SPVC_LEN 0x0C

MLXSW_REG_DEFINE(spvc, MLXSW_REG_SPVC_ID, MLXSW_REG_SPVC_LEN);

/* reg_spvc_local_port
 * Local port.
 * Access: Index
 *
 * Note: applies both to Rx port and Tx port, so if a packet traverses
 * through Rx port i and a Tx port j then port i and port j must have the
 * same configuration.
 */

MLXSW_ITEM32_LP(reg, spvc, 0x00, 16, 0x00, 12);

/* reg_spvc_inner_et2
 * Vlan Tag1 EtherType2 enable.
 * Packet is initially classified as double VLAN Tag if in addition to
 * being classified with a tag0 VLAN Tag its tag1 EtherType value is
 * equal to ether_type2.
 * 0: disable (default)
 * 1: enable
 * Access: RW
 */

MLXSW_ITEM32(reg, spvc, inner_et2, 0x08, 17, 1);

/* reg_spvc_et2
 * Vlan Tag0 EtherType2 enable.
 * Packet is initially classified as VLAN Tag if its tag0 EtherType is
 * equal to ether_type2.
 * 0: disable (default)
 * 1: enable
 * Access: RW
 */

MLXSW_ITEM32(reg, spvc, et2, 0x08, 16, 1);

/* reg_spvc_inner_et1
 * Vlan Tag1 EtherType1 enable.
 * Packet is initially classified as double VLAN Tag if in addition to
 * being classified with a tag0 VLAN Tag its tag1 EtherType value is
 * equal to ether_type1.
 * 0: disable
 * 1: enable (default)
 * Access: RW
 */

MLXSW_ITEM32(reg, spvc, inner_et1, 0x08, 9, 1);

/* reg_spvc_et1
 * Vlan Tag0 EtherType1 enable.
 * Packet is initially classified as VLAN Tag if its tag0 EtherType is
 * equal to ether_type1.
 * 0: disable
 * 1: enable (default)
 * Access: RW
 */

MLXSW_ITEM32(reg, spvc, et1, 0x08, 8, 1);

/* reg_inner_et0
 * Vlan Tag1 EtherType0 enable.
 * Packet is initially classified as double VLAN Tag if in addition to
 * being classified with a tag0 VLAN Tag its tag1 EtherType value is
 * equal to ether_type0.
 * 0: disable
 * 1: enable (default)
 * Access: RW
 */

MLXSW_ITEM32(reg, spvc, inner_et0, 0x08, 1, 1);

/* reg_et0
 * Vlan Tag0 EtherType0 enable.
 * Packet is initially classified as VLAN Tag if its tag0 EtherType is
 * equal to ether_type0.
 * 0: disable
 * 1: enable (default)
 * Access: RW
 */

MLXSW_ITEM32(reg, spvc, et0, 0x08, 0, 1);

static inline void mlxsw_reg_spvc_pack(char *payload, u16 local_port, bool et1,
           bool et0)
{
 MLXSW_REG_ZERO(spvc, payload);
 mlxsw_reg_spvc_local_port_set(payload, local_port);
 /* Enable inner_et1 and inner_et0 to enable identification of double
 * tagged packets.
 */

 mlxsw_reg_spvc_inner_et1_set(payload, 1);
 mlxsw_reg_spvc_inner_et0_set(payload, 1);
 mlxsw_reg_spvc_et1_set(payload, et1);
 mlxsw_reg_spvc_et0_set(payload, et0);
}

/* SFFP - Switch FID Flooding Profiles Register
 * --------------------------------------------
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=98 H=93 G=95

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.