diff options
author | Birger Koblitz <git@birger-koblitz.de> | 2022-01-18 14:20:40 +0100 |
---|---|---|
committer | Daniel Golle <daniel@makrotopia.org> | 2022-02-17 15:21:47 +0000 |
commit | 32e5b5ee6b86956d7f97736615bb56c8a28cd841 (patch) | |
tree | cbb519e8a79a834b080330e84a65c0e9b9ad1e6c /target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c | |
parent | 8557b458e204e9a290e7475a98c4293ba9ad4131 (diff) | |
download | upstream-32e5b5ee6b86956d7f97736615bb56c8a28cd841.tar.gz upstream-32e5b5ee6b86956d7f97736615bb56c8a28cd841.tar.bz2 upstream-32e5b5ee6b86956d7f97736615bb56c8a28cd841.zip |
realtek: Add Link Aggregation (aka trunking) support
This adds LAG support for all 4 SoC families, including support
ofr the use of different distribution algorithm for the load-
balancing between individual links.
Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
Signed-off-by: Birger Koblitz <git@birger-koblitz.de>
Diffstat (limited to 'target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c')
-rw-r--r-- | target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c index 5a90e53da2..ea08ca12fc 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c @@ -402,11 +402,15 @@ static int __init rtl83xx_get_l2aging(struct rtl838x_switch_priv *priv) } /* Caller must hold priv->reg_mutex */ -int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port) +int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_lag_upper_info *info) { struct rtl838x_switch_priv *priv = ds->priv; int i; - + u32 algomsk = 0; + u32 algoidx = 0; + if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) { + return -EINVAL; + } pr_info("%s: Adding port %d to LA-group %d\n", __func__, port, group); if (group >= priv->n_lags) { pr_err("Link Agrregation group too large.\n"); @@ -419,18 +423,40 @@ int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port) } for (i = 0; i < priv->n_lags; i++) { - if (priv->lags_port_members[i] & BIT_ULL(i)) + if (priv->lags_port_members[i] & BIT_ULL(port)) break; } if (i != priv->n_lags) { pr_err("%s: Port already member of LAG: %d\n", __func__, i); return -ENOSPC; } - + switch(info->hash_type) { + case NETDEV_LAG_HASH_L2: + algomsk |= TRUNK_DISTRIBUTION_ALGO_DMAC_BIT; + algomsk |= TRUNK_DISTRIBUTION_ALGO_SMAC_BIT; + break; + case NETDEV_LAG_HASH_L23: + algomsk |= TRUNK_DISTRIBUTION_ALGO_DMAC_BIT; + algomsk |= TRUNK_DISTRIBUTION_ALGO_SMAC_BIT; + algomsk |= TRUNK_DISTRIBUTION_ALGO_SIP_BIT; //source ip + algomsk |= TRUNK_DISTRIBUTION_ALGO_DIP_BIT; //dest ip + algoidx = 1; + break; + case NETDEV_LAG_HASH_L34: + algomsk |= TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT; //sport + algomsk |= TRUNK_DISTRIBUTION_ALGO_DST_L4PORT_BIT; //dport + algomsk |= TRUNK_DISTRIBUTION_ALGO_SIP_BIT; //source ip + algomsk |= TRUNK_DISTRIBUTION_ALGO_DIP_BIT; //dest ip + algoidx = 2; + break; + default: + algomsk |= 0x7f; + } + priv->r->set_distribution_algorithm(group, algoidx, algomsk); priv->r->mask_port_reg_be(0, BIT_ULL(port), priv->r->trk_mbr_ctr(group)); priv->lags_port_members[group] |= BIT_ULL(port); - pr_info("lags_port_members %d now %016llx\n", group, priv->lags_port_members[group]); + pr_debug("lags_port_members %d now %016llx\n", group, priv->lags_port_members[group]); return 0; } @@ -453,11 +479,10 @@ int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port) if (!(priv->lags_port_members[group] & BIT_ULL(port))) { - pr_err("%s: Port not member of LAG: %d\n", __func__, group - ); + pr_err("%s: Port not member of LAG: %d\n", __func__, group); return -ENOSPC; } - + // 0x7f algo mask all priv->r->mask_port_reg_be(BIT_ULL(port), 0, priv->r->trk_mbr_ctr(group)); priv->lags_port_members[group] &= ~BIT_ULL(port); @@ -625,6 +650,7 @@ static int rtl83xx_handle_changeupper(struct rtl838x_switch_priv *priv, struct netdev_notifier_changeupper_info *info) { struct net_device *upper = info->upper_dev; + struct netdev_lag_upper_info *lag_upper_info = NULL; int i, j, err; if (!netif_is_lag_master(upper)) @@ -646,9 +672,10 @@ static int rtl83xx_handle_changeupper(struct rtl838x_switch_priv *priv, } if (info->linking) { + lag_upper_info = info->upper_info; if (!priv->lag_devs[i]) priv->lag_devs[i] = upper; - err = rtl83xx_lag_add(priv->ds, i, priv->ports[j].dp->index); + err = rtl83xx_lag_add(priv->ds, i, priv->ports[j].dp->index, lag_upper_info); if (err) { err = -EINVAL; goto out; |