mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 12:52:29 -04:00
Merge branch 'dpaa2-switch-add-support-for-lag-offload'
Ioana Ciornei says: ==================== dpaa2-switch: add support for LAG offload This patch set adds support in dpaa2-switch for offloading upper bond devices. The first two patches remove the necessity to hold rtnl_lock during the event processing workqueue by ensuring that all event were processed before any changes in FDB layout happens. Patch #3 updates the logic around choosing the FDB that should be used on a switch port. This is necessary since with the addition of the LAG offload, we need to take into account all ports which are under the same bridge, even though not directly. The next four patches clean up the FDB event by making them easier to integrate with bond devices and also add the dpaa2_switch_port_to_bridge_port() helper to be used in the LAG offload support. The 8th patch adds the necessary new APIs for the LAG configuration while the next one uses them, both in the prechangeupper phase and the changeupper one. Which ports can be part of the same LAG group is configurable at boot time, thus we use the prechangeupper callback in order to validate that a requested configuration can be offloaded or not. This set also extends the handling of FDBs and port objects so that they are handled by the driver even on an offloaded bond device. v3: https://lore.kernel.org/all/20260603143623.3712024-1-ioana.ciornei@nxp.com/ v2: https://lore.kernel.org/all/20260512131554.952971-1-ioana.ciornei@nxp.com/ v1: https://lore.kernel.org/all/20260506151540.1242997-1-ioana.ciornei@nxp.com/ ==================== Link: https://patch.msgid.link/20260629112309.154328-1-ioana.ciornei@nxp.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -41,7 +41,8 @@
|
||||
#define ETHSW_MAX_FRAME_LENGTH (DPAA2_MFL - VLAN_ETH_HLEN - ETH_FCS_LEN)
|
||||
#define ETHSW_L2_MAX_FRM(mtu) ((mtu) + VLAN_ETH_HLEN + ETH_FCS_LEN)
|
||||
|
||||
#define ETHSW_FEATURE_MAC_ADDR BIT(0)
|
||||
#define ETHSW_FEATURE_MAC_ADDR BIT(0)
|
||||
#define ETHSW_FEATURE_LAG_OFFLOAD BIT(1)
|
||||
|
||||
/* Number of receive queues (one RX and one TX_CONF) */
|
||||
#define DPAA2_SWITCH_RX_NUM_FQS 2
|
||||
@@ -86,6 +87,9 @@
|
||||
|
||||
#define DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE 256
|
||||
|
||||
#define DPAA2_ETHSW_FLC_IF_ID(flc) (((flc) >> 32) & GENMASK(15, 0))
|
||||
#define DPAA2_ETHSW_FLC_IMPRECISE_IF_ID(flc) ((flc) & BIT_ULL(63))
|
||||
|
||||
extern const struct ethtool_ops dpaa2_switch_port_ethtool_ops;
|
||||
|
||||
struct ethsw_core;
|
||||
@@ -99,12 +103,30 @@ struct dpaa2_switch_fq {
|
||||
u32 fqid;
|
||||
};
|
||||
|
||||
struct dpaa2_mac_addr {
|
||||
unsigned char addr[ETH_ALEN];
|
||||
u16 vid;
|
||||
refcount_t refcount;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct dpaa2_switch_fdb {
|
||||
struct net_device *bridge_dev;
|
||||
u16 fdb_id;
|
||||
bool in_use;
|
||||
};
|
||||
|
||||
struct dpaa2_switch_lag {
|
||||
struct ethsw_core *ethsw;
|
||||
struct net_device *bond_dev;
|
||||
bool in_use;
|
||||
u8 id;
|
||||
struct ethsw_port_priv *primary;
|
||||
/* Protects the list of fdbs installed on this LAG */
|
||||
struct mutex fdb_lock;
|
||||
struct list_head fdbs;
|
||||
};
|
||||
|
||||
struct dpaa2_switch_acl_entry {
|
||||
struct list_head list;
|
||||
u16 prio;
|
||||
@@ -163,6 +185,8 @@ struct ethsw_port_priv {
|
||||
struct dpaa2_mac *mac;
|
||||
/* Protects against changes to port_priv->mac */
|
||||
struct mutex mac_lock;
|
||||
|
||||
struct dpaa2_switch_lag __rcu *lag;
|
||||
};
|
||||
|
||||
/* Switch data */
|
||||
@@ -190,6 +214,8 @@ struct ethsw_core {
|
||||
struct dpaa2_switch_fdb *fdbs;
|
||||
struct dpaa2_switch_filter_block *filter_blocks;
|
||||
u16 mirror_port;
|
||||
|
||||
struct dpaa2_switch_lag *lags;
|
||||
};
|
||||
|
||||
static inline int dpaa2_switch_get_index(struct ethsw_core *ethsw,
|
||||
@@ -274,4 +300,18 @@ int dpaa2_switch_block_offload_mirror(struct dpaa2_switch_filter_block *block,
|
||||
|
||||
int dpaa2_switch_block_unoffload_mirror(struct dpaa2_switch_filter_block *block,
|
||||
struct ethsw_port_priv *port_priv);
|
||||
|
||||
static inline bool
|
||||
dpaa2_switch_port_offloads_bridge_port(struct ethsw_port_priv *port_priv,
|
||||
const struct net_device *dev)
|
||||
{
|
||||
struct dpaa2_switch_lag *lag = rcu_dereference_rtnl(port_priv->lag);
|
||||
|
||||
if (lag && lag->bond_dev == dev)
|
||||
return true;
|
||||
if (port_priv->netdev == dev)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* __ETHSW_H */
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
/* DPSW Version */
|
||||
#define DPSW_VER_MAJOR 8
|
||||
#define DPSW_VER_MINOR 9
|
||||
#define DPSW_VER_MINOR 13
|
||||
|
||||
#define DPSW_CMD_BASE_VERSION 1
|
||||
#define DPSW_CMD_VERSION_2 2
|
||||
@@ -92,11 +92,14 @@
|
||||
#define DPSW_CMDID_CTRL_IF_SET_POOLS DPSW_CMD_ID(0x0A1)
|
||||
#define DPSW_CMDID_CTRL_IF_ENABLE DPSW_CMD_ID(0x0A2)
|
||||
#define DPSW_CMDID_CTRL_IF_DISABLE DPSW_CMD_ID(0x0A3)
|
||||
#define DPSW_CMDID_SET_LAG DPSW_CMD_V2(0x0A4)
|
||||
#define DPSW_CMDID_CTRL_IF_SET_QUEUE DPSW_CMD_ID(0x0A6)
|
||||
|
||||
#define DPSW_CMDID_SET_EGRESS_FLOOD DPSW_CMD_ID(0x0AC)
|
||||
#define DPSW_CMDID_IF_SET_LEARNING_MODE DPSW_CMD_ID(0x0AD)
|
||||
|
||||
#define DPSW_CMDID_IF_SET_LAG_STATE DPSW_CMD_ID(0x0B0)
|
||||
|
||||
/* Macros for accessing command fields smaller than 1byte */
|
||||
#define DPSW_MASK(field) \
|
||||
GENMASK(DPSW_##field##_SHIFT + DPSW_##field##_SIZE - 1, \
|
||||
@@ -552,5 +555,18 @@ struct dpsw_cmd_if_reflection {
|
||||
/* only 2 bits from the LSB */
|
||||
u8 filter;
|
||||
};
|
||||
|
||||
struct dpsw_cmd_lag {
|
||||
u8 group_id;
|
||||
u8 num_ifs;
|
||||
u8 pad[6];
|
||||
u8 if_id[DPSW_MAX_LAG_IFS];
|
||||
u8 phase;
|
||||
};
|
||||
|
||||
struct dpsw_cmd_if_set_lag_state {
|
||||
__le16 if_id;
|
||||
u8 tx_enabled;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
#endif /* __FSL_DPSW_CMD_H */
|
||||
|
||||
@@ -1659,3 +1659,63 @@ int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
|
||||
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* dpsw_lag_set() - Set LAG configuration
|
||||
* @mc_io: Pointer to MC portal's I/O object
|
||||
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
|
||||
* @token: Token of DPSW object
|
||||
* @cfg: pointer to LAG configuration
|
||||
*
|
||||
* Return: '0' on Success; Error code otherwise.
|
||||
*/
|
||||
int dpsw_lag_set(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
|
||||
const struct dpsw_lag_cfg *cfg)
|
||||
{
|
||||
struct fsl_mc_command cmd = { 0 };
|
||||
struct dpsw_cmd_lag *cmd_params;
|
||||
int i = 0;
|
||||
|
||||
cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_LAG, cmd_flags, token);
|
||||
|
||||
if (cfg->num_ifs > DPSW_MAX_LAG_IFS)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
cmd_params = (struct dpsw_cmd_lag *)cmd.params;
|
||||
cmd_params->group_id = cfg->group_id;
|
||||
cmd_params->num_ifs = cfg->num_ifs;
|
||||
cmd_params->phase = cfg->phase;
|
||||
|
||||
for (i = 0; i < cfg->num_ifs; i++)
|
||||
cmd_params->if_id[i] = cfg->if_id[i];
|
||||
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* dpsw_if_set_lag_state() - Change per port LAG state
|
||||
* @mc_io: Pointer to MC portal's I/O object
|
||||
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
|
||||
* @token: Token of DPSW object
|
||||
* @if_id: ID of the switch interface
|
||||
* @tx_enabled: Value of the per port LAG state
|
||||
* - 0 if the interface will not be active as part of the LAG group
|
||||
* - 1 if the interface will be active in the LAG group
|
||||
*
|
||||
* Return: '0' on Success; Error code otherwise.
|
||||
*/
|
||||
int dpsw_if_set_lag_state(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
|
||||
u16 if_id, u8 tx_enabled)
|
||||
{
|
||||
struct dpsw_cmd_if_set_lag_state *cmd_params;
|
||||
struct fsl_mc_command cmd = { 0 };
|
||||
|
||||
cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_LAG_STATE,
|
||||
cmd_flags, token);
|
||||
|
||||
cmd_params = (struct dpsw_cmd_if_set_lag_state *)cmd.params;
|
||||
cmd_params->if_id = cpu_to_le16(if_id);
|
||||
cmd_params->tx_enabled = tx_enabled;
|
||||
|
||||
return mc_send_command(mc_io, &cmd);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ struct fsl_mc_io;
|
||||
|
||||
#define DPSW_MAX_IF 64
|
||||
|
||||
#define DPSW_MAX_LAG_IFS 8
|
||||
|
||||
int dpsw_open(struct fsl_mc_io *mc_io, u32 cmd_flags, int dpsw_id, u16 *token);
|
||||
|
||||
int dpsw_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token);
|
||||
@@ -788,4 +790,32 @@ int dpsw_if_add_reflection(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
|
||||
|
||||
int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
|
||||
u16 if_id, const struct dpsw_reflection_cfg *cfg);
|
||||
|
||||
/* Link Aggregation Group configuration */
|
||||
|
||||
#define DPSW_LAG_SET_PHASE_APPLY 0
|
||||
#define DPSW_LAG_SET_PHASE_CHECK 1
|
||||
|
||||
/**
|
||||
* struct dpsw_lag_cfg - Configuration structure for a LAG group
|
||||
* @group_id: Link aggregation group ID. Valid values are in the
|
||||
* [1, DPSW_MAX_LAG_IFS] range.
|
||||
* @num_ifs: Number of interfaces in this LAG group, valid range is
|
||||
* [0, DPSW_MAX_LAG_IFS].
|
||||
* @if_id: Array containing the interface IDs of the ports part of a LAG group
|
||||
* @phase: Use DPSW_LAG_SET_PHASE_APPLY for LAG configuration processing or
|
||||
* DPSW_LAG_SET_PHASE_CHECK for LAG configuration validation.
|
||||
*/
|
||||
struct dpsw_lag_cfg {
|
||||
u8 group_id;
|
||||
u8 num_ifs;
|
||||
u8 if_id[DPSW_MAX_LAG_IFS];
|
||||
u8 phase;
|
||||
};
|
||||
|
||||
int dpsw_lag_set(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
|
||||
const struct dpsw_lag_cfg *cfg);
|
||||
|
||||
int dpsw_if_set_lag_state(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
|
||||
u16 if_id, u8 tx_enabled);
|
||||
#endif /* __FSL_DPSW_H */
|
||||
|
||||
Reference in New Issue
Block a user