Commit 3a17ea77 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'mlxsw-preparations-for-support-of-cff-flood-mode'

Petr Machata says:

====================
mlxsw: Preparations for support of CFF flood mode

PGT is an in-HW table that maps addresses to sets of ports. Then when some
HW process needs a set of ports as an argument, instead of embedding the
actual set in the dynamic configuration, what gets configured is the
address referencing the set. The HW then works with the appropriate PGT
entry.

Among other allocations, the PGT currently contains two large blocks for
bridge flooding: one for 802.1q and one for 802.1d. Within each of these
blocks are three tables, for unknown-unicast, multicast and broadcast
flooding:

      . . . |    802.1q    |    802.1d    | . . .
            | UC | MC | BC | UC | MC | BC |
             \______ _____/ \_____ ______/
                    v             v
                   FID flood vectors

Thus each FID (which corresponds to an 802.1d bridge or one VLAN in an
802.1q bridge) uses three flood vectors spread across a fairly large region
of PGT.

This way of organizing the flood table (called "controlled") is not very
flexible. E.g. to decrease a bridge scale and store more IP MC vectors, one
would need to completely rewrite the bridge PGT blocks, or resort to hacks
such as storing individual MC flood vectors into unused part of the bridge
table.

In order to address these shortcomings, Spectrum-2 and above support what
is called CFF flood mode, for Compressed FID Flooding. In CFF flood mode,
each FID has a little table of its own, with three entries adjacent to each
other, one for unknown-UC, one for MC, one for BC. This allows for a much
more fine-grained approach to PGT management, where bits of it are
allocated on demand.

      . . . | FID | FID | FID | FID | FID | . . .
            |U|M|B|U|M|B|U|M|B|U|M|B|U|M|B|
             \_____________ _____________/
                           v
                   FID flood vectors

Besides the FID table organization, the CFF flood mode also impacts Router
Subport (RSP) table. This table contains flood vectors for rFIDs, which are
FIDs that reference front panel ports or LAGs. The RSP table contains two
entries per front panel port and LAG, one for unknown-UC traffic, and one
for everything else. Currently, the FW allocates and manages the table in
its own part of PGT. rFIDs are marked with flood_rsp bit and managed
specially. In CFF mode, rFIDs are managed as all other FIDs. The driver
therefore has to allocate and maintain the flood vectors. Like with bridge
FIDs, this is more work, but increases flexibility of the system.

The FW currently supports both the controlled and CFF flood modes. To shed
complexity, in the future it should only support CFF flood mode. Hence this
patchset, which is the first in series of two to add CFF flood mode support
to mlxsw.

There are FW versions out there that do not support CFF flood mode, and on
Spectrum-1 in particular, there is no plan to support it at all. mlxsw will
therefore have to support both controlled flood mode as well as CFF.

Another aspect is that at least on Spectrum-1, there are FW versions out
there that claim to support CFF flood mode, but then reject or ignore
configurations enabling the same. The driver thus has to have a say in
whether an attempt to configure CFF flood mode should even be made.

Much like with the LAG mode, the feature is therefore expressed in terms of
"does the driver prefer CFF flood mode?", and "what flood mode the PCI
module managed to configure the FW with". This gives to the driver a chance
to determine whether CFF flood mode configuration should be attempted.

In this patchset, we lay the ground with new definitions, registers and
their fields, and some minor code shaping. The next patchset will be more
focused on introducing necessary abstractions and implementation.

- Patches #1 and #2 add CFF-related items to the command interface.

- Patch #3 adds a new resource, for maximum number of flood profiles
  supported. (A flood profile is a mapping between traffic type and offset
  in the per-FID flood vector table.)

- Patches #4 to #8 adjust reg.h. The SFFP register is added, which is used
  for configuring the abovementioned traffic-type-to-offset mapping. The
  SFMR, register, which serves for FID configuration, is extended with
  fields specific to CFF mode. And other minor adjustments.

- Patches #9 and #10 add the plumbing for CFF mode: a way to request that
  CFF flood mode be configured, and a way to query the flood mode that was
  actually configured.

- Patch #11 removes dead code.

- Patches #12 and #13 add helpers that the next patchset will make use of.
  Patch #14 moves RIF setup ahead so that FID code can make use of it.
====================

Link: https://lore.kernel.org/r/cover.1700503643.git.petrm@nvidia.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents dd891b5b f7ebb402
......@@ -282,6 +282,12 @@ MLXSW_ITEM32(cmd_mbox, query_fw, fw_day, 0x14, 0, 8);
*/
MLXSW_ITEM32(cmd_mbox, query_fw, lag_mode_support, 0x18, 1, 1);
/* cmd_mbox_query_fw_cff_support
* 0: CONFIG_PROFILE.flood_mode = 5 (CFF) is not supported by FW
* 1: CONFIG_PROFILE.flood_mode = 5 (CFF) is supported by FW
*/
MLXSW_ITEM32(cmd_mbox, query_fw, cff_support, 0x18, 2, 1);
/* cmd_mbox_query_fw_clr_int_base_offset
* Clear Interrupt register's offset from clr_int_bar register
* in PCI address space.
......@@ -779,6 +785,11 @@ enum mlxsw_cmd_mbox_config_profile_flood_mode {
* used.
*/
MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CONTROLLED = 4,
/* CFF - Compressed FID Flood (CFF) mode.
* Reserved when legacy bridge model is used.
* Supported only by Spectrum-2+.
*/
MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CFF = 5,
};
/* cmd_mbox_config_profile_flood_mode
......
......@@ -211,6 +211,13 @@ mlxsw_core_lag_mode(struct mlxsw_core *mlxsw_core)
}
EXPORT_SYMBOL(mlxsw_core_lag_mode);
enum mlxsw_cmd_mbox_config_profile_flood_mode
mlxsw_core_flood_mode(struct mlxsw_core *mlxsw_core)
{
return mlxsw_core->bus->flood_mode(mlxsw_core->bus_priv);
}
EXPORT_SYMBOL(mlxsw_core_flood_mode);
void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core)
{
return mlxsw_core->driver_priv;
......
......@@ -38,6 +38,8 @@ unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core);
int mlxsw_core_max_lag(struct mlxsw_core *mlxsw_core, u16 *p_max_lag);
enum mlxsw_cmd_mbox_config_profile_lag_mode
mlxsw_core_lag_mode(struct mlxsw_core *mlxsw_core);
enum mlxsw_cmd_mbox_config_profile_flood_mode
mlxsw_core_flood_mode(struct mlxsw_core *mlxsw_core);
void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core);
......@@ -322,7 +324,12 @@ struct mlxsw_config_profile {
u16 max_regions;
u8 max_flood_tables;
u8 max_vid_flood_tables;
/* Flood mode to use if used_flood_mode. If flood_mode_prefer_cff,
* the backup flood mode (if any) when CFF unsupported.
*/
u8 flood_mode;
u8 max_fid_offset_flood_tables;
u16 fid_offset_flood_table_size;
u8 max_fid_flood_tables;
......@@ -338,6 +345,7 @@ struct mlxsw_config_profile {
u8 kvd_hash_double_parts;
u8 cqe_time_stamp_type;
bool lag_mode_prefer_sw;
bool flood_mode_prefer_cff;
struct mlxsw_swid_config swid_config[MLXSW_CONFIG_PROFILE_SWID_COUNT];
};
......@@ -489,6 +497,7 @@ struct mlxsw_bus {
u32 (*read_utc_sec)(void *bus_priv);
u32 (*read_utc_nsec)(void *bus_priv);
enum mlxsw_cmd_mbox_config_profile_lag_mode (*lag_mode)(void *bus_priv);
enum mlxsw_cmd_mbox_config_profile_flood_mode (*flood_mode)(void *priv);
u8 features;
};
......
......@@ -106,7 +106,9 @@ struct mlxsw_pci {
u64 utc_sec_offset;
u64 utc_nsec_offset;
bool lag_mode_support;
bool cff_support;
enum mlxsw_cmd_mbox_config_profile_lag_mode lag_mode;
enum mlxsw_cmd_mbox_config_profile_flood_mode flood_mode;
struct mlxsw_pci_queue_type_group queues[MLXSW_PCI_QUEUE_TYPE_COUNT];
u32 doorbell_offset;
struct mlxsw_core *core;
......@@ -1246,11 +1248,22 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox,
mlxsw_cmd_mbox_config_profile_fid_flood_table_size_set(
mbox, profile->fid_flood_table_size);
}
if (profile->used_flood_mode) {
if (profile->flood_mode_prefer_cff && mlxsw_pci->cff_support) {
enum mlxsw_cmd_mbox_config_profile_flood_mode flood_mode =
MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CFF;
mlxsw_cmd_mbox_config_profile_set_flood_mode_set(mbox, 1);
mlxsw_cmd_mbox_config_profile_flood_mode_set(mbox, flood_mode);
mlxsw_pci->flood_mode = flood_mode;
} else if (profile->used_flood_mode) {
mlxsw_cmd_mbox_config_profile_set_flood_mode_set(
mbox, 1);
mlxsw_cmd_mbox_config_profile_flood_mode_set(
mbox, profile->flood_mode);
mlxsw_pci->flood_mode = profile->flood_mode;
} else {
WARN_ON(1);
return -EINVAL;
}
if (profile->used_max_ib_mc) {
mlxsw_cmd_mbox_config_profile_set_max_ib_mc_set(
......@@ -1654,6 +1667,9 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
mlxsw_pci->lag_mode_support =
mlxsw_cmd_mbox_query_fw_lag_mode_support_get(mbox);
mlxsw_pci->cff_support =
mlxsw_cmd_mbox_query_fw_cff_support_get(mbox);
num_pages = mlxsw_cmd_mbox_query_fw_fw_pages_get(mbox);
err = mlxsw_pci_fw_area_init(mlxsw_pci, mbox, num_pages);
if (err)
......@@ -1970,6 +1986,14 @@ mlxsw_pci_lag_mode(void *bus_priv)
return mlxsw_pci->lag_mode;
}
static enum mlxsw_cmd_mbox_config_profile_flood_mode
mlxsw_pci_flood_mode(void *bus_priv)
{
struct mlxsw_pci *mlxsw_pci = bus_priv;
return mlxsw_pci->flood_mode;
}
static const struct mlxsw_bus mlxsw_pci_bus = {
.kind = "pci",
.init = mlxsw_pci_init,
......@@ -1982,6 +2006,7 @@ static const struct mlxsw_bus mlxsw_pci_bus = {
.read_utc_sec = mlxsw_pci_read_utc_sec,
.read_utc_nsec = mlxsw_pci_read_utc_nsec,
.lag_mode = mlxsw_pci_lag_mode,
.flood_mode = mlxsw_pci_flood_mode,
.features = MLXSW_BUS_F_TXRX | MLXSW_BUS_F_RESET,
};
......
......@@ -1024,6 +1024,8 @@ static inline void mlxsw_reg_spaft_pack(char *payload, u16 local_port,
* ------------------------------------------
* 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
......@@ -1862,6 +1864,7 @@ MLXSW_ITEM32(reg, sfmr, fid, 0x00, 0, 16);
* 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);
......@@ -1872,6 +1875,7 @@ MLXSW_ITEM32(reg, sfmr, flood_rsp, 0x08, 31, 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);
......@@ -1880,6 +1884,8 @@ MLXSW_ITEM32(reg, sfmr, flood_bridge_type, 0x08, 28, 1);
* 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);
......@@ -1938,6 +1944,26 @@ MLXSW_ITEM32(reg, sfmr, irif_v, 0x14, 24, 1);
*/
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_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
......@@ -1959,18 +1985,11 @@ 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,
u16 fid_offset, bool flood_rsp,
enum mlxsw_reg_bridge_type bridge_type,
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_fid_offset_set(payload, fid_offset);
mlxsw_reg_sfmr_vtfp_set(payload, false);
mlxsw_reg_sfmr_vv_set(payload, false);
mlxsw_reg_sfmr_flood_rsp_set(payload, flood_rsp);
mlxsw_reg_sfmr_flood_bridge_type_set(payload, bridge_type);
mlxsw_reg_sfmr_smpe_valid_set(payload, smpe_valid);
mlxsw_reg_sfmr_smpe_set(payload, smpe);
}
......@@ -2168,6 +2187,50 @@ static inline void mlxsw_reg_spvc_pack(char *payload, u16 local_port, bool et1,
mlxsw_reg_spvc_et0_set(payload, et0);
}
/* SFFP - Switch FID Flooding Profiles Register
* --------------------------------------------
* The SFFP register populates the fid flooding profile tables used for the NVE
* flooding and Compressed-FID Flooding (CFF).
*
* Reserved on Spectrum-1.
*/
#define MLXSW_REG_SFFP_ID 0x2029
#define MLXSW_REG_SFFP_LEN 0x0C
MLXSW_REG_DEFINE(sffp, MLXSW_REG_SFFP_ID, MLXSW_REG_SFFP_LEN);
/* reg_sffp_profile_id
* Profile ID a.k.a. SFMR.nve_flood_prf_id or SFMR.cff_prf_id
* Range 0..max_cap_nve_flood_prf-1
* Access: Index
*/
MLXSW_ITEM32(reg, sffp, profile_id, 0x00, 16, 2);
/* reg_sffp_type
* The traffic type to reach the flooding table.
* Same as SFGC.type
* Access: Index
*/
MLXSW_ITEM32(reg, sffp, type, 0x00, 0, 4);
/* reg_sffp_flood_offset
* Flood offset. Offset to add to SFMR.cff_mid_base to get the final PGT address
* for FID flood; or offset to add to SFMR.nve_tunnel_flood_ptr to get KVD
* pointer for NVE underlay.
* Access: RW
*/
MLXSW_ITEM32(reg, sffp, flood_offset, 0x04, 0, 3);
static inline void mlxsw_reg_sffp_pack(char *payload, u8 profile_id,
enum mlxsw_reg_sfgc_type type,
u8 flood_offset)
{
MLXSW_REG_ZERO(sffp, payload);
mlxsw_reg_sffp_profile_id_set(payload, profile_id);
mlxsw_reg_sffp_type_set(payload, type);
mlxsw_reg_sffp_flood_offset_set(payload, flood_offset);
}
/* SPEVET - Switch Port Egress VLAN EtherType
* ------------------------------------------
* The switch port egress VLAN EtherType configures which EtherType to push at
......@@ -12946,6 +13009,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
MLXSW_REG(spvmlr),
MLXSW_REG(spfsr),
MLXSW_REG(spvc),
MLXSW_REG(sffp),
MLXSW_REG(spevet),
MLXSW_REG(smpe),
MLXSW_REG(smid2),
......
......@@ -27,6 +27,7 @@ enum mlxsw_res_id {
MLXSW_RES_ID_FID,
MLXSW_RES_ID_MAX_LAG,
MLXSW_RES_ID_MAX_LAG_MEMBERS,
MLXSW_RES_ID_MAX_NVE_FLOOD_PRF,
MLXSW_RES_ID_GUARANTEED_SHARED_BUFFER,
MLXSW_RES_ID_CELL_SIZE,
MLXSW_RES_ID_MAX_HEADROOM_SIZE,
......@@ -88,6 +89,7 @@ static u16 mlxsw_res_ids[] = {
[MLXSW_RES_ID_FID] = 0x2512,
[MLXSW_RES_ID_MAX_LAG] = 0x2520,
[MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521,
[MLXSW_RES_ID_MAX_NVE_FLOOD_PRF] = 0x2522,
[MLXSW_RES_ID_GUARANTEED_SHARED_BUFFER] = 0x2805, /* Bytes */
[MLXSW_RES_ID_CELL_SIZE] = 0x2803, /* Bytes */
[MLXSW_RES_ID_MAX_HEADROOM_SIZE] = 0x2811, /* Bytes */
......
......@@ -753,6 +753,8 @@ union mlxsw_sp_l3addr {
};
u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif);
int mlxsw_sp_rif_subport_port(const struct mlxsw_sp_rif *rif,
u16 *port, bool *is_lag);
int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
struct netlink_ext_ack *extack);
void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp);
......
......@@ -424,18 +424,35 @@ static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
MLXSW_REG_SFMR_OP_DESTROY_FID;
}
static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
static void mlxsw_sp_fid_pack(char *sfmr_pl,
const struct mlxsw_sp_fid *fid,
enum mlxsw_reg_sfmr_op op)
{
struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
char sfmr_pl[MLXSW_REG_SFMR_LEN];
u16 smpe;
smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0;
mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid->fid_index,
fid->fid_offset, fid->fid_family->flood_rsp,
fid->fid_family->bridge_type,
mlxsw_reg_sfmr_pack(sfmr_pl, op, fid->fid_index,
fid->fid_family->smpe_index_valid, smpe);
}
static void mlxsw_sp_fid_pack_ctl(char *sfmr_pl,
const struct mlxsw_sp_fid *fid,
enum mlxsw_reg_sfmr_op op)
{
mlxsw_sp_fid_pack(sfmr_pl, fid, op);
mlxsw_reg_sfmr_fid_offset_set(sfmr_pl, fid->fid_offset);
mlxsw_reg_sfmr_flood_rsp_set(sfmr_pl, fid->fid_family->flood_rsp);
mlxsw_reg_sfmr_flood_bridge_type_set(sfmr_pl,
fid->fid_family->bridge_type);
}
static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
{
struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
char sfmr_pl[MLXSW_REG_SFMR_LEN];
mlxsw_sp_fid_pack_ctl(sfmr_pl, fid, mlxsw_sp_sfmr_op(valid));
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
}
......@@ -444,15 +461,8 @@ static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid,
{
struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
char sfmr_pl[MLXSW_REG_SFMR_LEN];
u16 smpe;
smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0;
mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID,
fid->fid_index, fid->fid_offset,
fid->fid_family->flood_rsp,
fid->fid_family->bridge_type,
fid->fid_family->smpe_index_valid, smpe);
mlxsw_sp_fid_pack_ctl(sfmr_pl, fid, MLXSW_REG_SFMR_OP_CREATE_FID);
mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid);
mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni));
mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid);
......@@ -1687,9 +1697,6 @@ mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
int err;
int i;
if (!fid_family->nr_flood_tables)
return 0;
pgt_size = mlxsw_sp_fid_family_pgt_size(fid_family);
err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &fid_family->pgt_base,
pgt_size);
......@@ -1718,9 +1725,6 @@ mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family)
struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
u16 pgt_size;
if (!fid_family->nr_flood_tables)
return;
pgt_size = mlxsw_sp_fid_family_pgt_size(fid_family);
mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size);
}
......
......@@ -8419,6 +8419,9 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
rif->ops = ops;
rif->rif_entries = rif_entries;
if (ops->setup)
ops->setup(rif, params);
if (ops->fid_get) {
fid = ops->fid_get(rif, params, extack);
if (IS_ERR(fid)) {
......@@ -8428,9 +8431,6 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
rif->fid = fid;
}
if (ops->setup)
ops->setup(rif, params);
err = ops->configure(rif, extack);
if (err)
goto err_configure;
......@@ -8660,6 +8660,20 @@ mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif *rif)
return container_of(rif, struct mlxsw_sp_rif_subport, common);
}
int mlxsw_sp_rif_subport_port(const struct mlxsw_sp_rif *rif,
u16 *port, bool *is_lag)
{
struct mlxsw_sp_rif_subport *rif_subport;
if (WARN_ON(rif->ops->type != MLXSW_SP_RIF_TYPE_SUBPORT))
return -EINVAL;
rif_subport = mlxsw_sp_rif_subport_rif(rif);
*is_lag = rif_subport->lag;
*port = *is_lag ? rif_subport->lag_id : rif_subport->system_port;
return 0;
}
static struct mlxsw_sp_rif *
mlxsw_sp_rif_subport_get(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_rif_params *params,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment