diff options
Diffstat (limited to 'target/linux')
4 files changed, 80 insertions, 4 deletions
diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index a1b9841473..817aca57d5 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -1076,10 +1076,25 @@ ar8216_set_mirror_regs(struct ar8xxx_priv *priv) AR8216_PORT_CTRL_MIRROR_TX); } +static inline u32 +ar8xxx_age_time_val(int age_time) +{ + return (age_time + AR8XXX_REG_ARL_CTRL_AGE_TIME_SECS / 2) / + AR8XXX_REG_ARL_CTRL_AGE_TIME_SECS; +} + +static inline void +ar8xxx_set_age_time(struct ar8xxx_priv *priv, int reg) +{ + u32 age_time = ar8xxx_age_time_val(priv->arl_age_time); + ar8xxx_rmw(priv, reg, AR8216_ATU_CTRL_AGE_TIME, age_time << AR8216_ATU_CTRL_AGE_TIME_S); +} + int ar8xxx_sw_hw_apply(struct switch_dev *dev) { struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + const struct ar8xxx_chip *chip = priv->chip; u8 portmask[AR8X16_MAX_PORTS]; int i, j; @@ -1103,8 +1118,8 @@ ar8xxx_sw_hw_apply(struct switch_dev *dev) portmask[i] |= vp & ~mask; } - priv->chip->vtu_load_vlan(priv, priv->vlan_id[j], - priv->vlan_table[j]); + chip->vtu_load_vlan(priv, priv->vlan_id[j], + priv->vlan_table[j]); } } else { /* vlan disabled: @@ -1120,10 +1135,14 @@ ar8xxx_sw_hw_apply(struct switch_dev *dev) /* update the port destination mask registers and tag settings */ for (i = 0; i < dev->ports; i++) { - priv->chip->setup_port(priv, i, portmask[i]); + chip->setup_port(priv, i, portmask[i]); } - priv->chip->set_mirror_regs(priv); + chip->set_mirror_regs(priv); + + /* set age time */ + if (chip->reg_arl_ctrl) + ar8xxx_set_age_time(priv, chip->reg_arl_ctrl); mutex_unlock(&priv->reg_mutex); return 0; @@ -1151,6 +1170,7 @@ ar8xxx_sw_reset_switch(struct switch_dev *dev) priv->mirror_tx = false; priv->source_port = 0; priv->monitor_port = 0; + priv->arl_age_time = AR8XXX_DEFAULT_ARL_AGE_TIME; chip->init_globals(priv); @@ -1407,6 +1427,34 @@ unlock: } int +ar8xxx_sw_set_arl_age_time(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int age_time = val->value.i; + u32 age_time_val; + + if (age_time < 0) + return -EINVAL; + + age_time_val = ar8xxx_age_time_val(age_time); + if (age_time_val == 0 || age_time_val > 0xffff) + return -EINVAL; + + priv->arl_age_time = age_time; + return 0; +} + +int +ar8xxx_sw_get_arl_age_time(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + val->value.i = priv->arl_age_time; + return 0; +} + +int ar8xxx_sw_get_arl_table(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) @@ -1633,6 +1681,7 @@ static const struct ar8xxx_chip ar8216_chip = { .reg_port_stats_start = 0x19000, .reg_port_stats_length = 0xa0, + .reg_arl_ctrl = AR8216_REG_ATU_CTRL, .name = "Atheros AR8216", .ports = AR8216_NUM_PORTS, @@ -1662,6 +1711,7 @@ static const struct ar8xxx_chip ar8236_chip = { .reg_port_stats_start = 0x20000, .reg_port_stats_length = 0x100, + .reg_arl_ctrl = AR8216_REG_ATU_CTRL, .name = "Atheros AR8236", .ports = AR8216_NUM_PORTS, @@ -1691,6 +1741,7 @@ static const struct ar8xxx_chip ar8316_chip = { .reg_port_stats_start = 0x20000, .reg_port_stats_length = 0x100, + .reg_arl_ctrl = AR8216_REG_ATU_CTRL, .name = "Atheros AR8316", .ports = AR8216_NUM_PORTS, diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.h b/target/linux/generic/files/drivers/net/phy/ar8216.h index 14fe928fe0..fb961ff04c 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.h +++ b/target/linux/generic/files/drivers/net/phy/ar8216.h @@ -33,6 +33,9 @@ #define AR8X16_PROBE_RETRIES 10 #define AR8X16_MAX_PORTS 8 +#define AR8XXX_REG_ARL_CTRL_AGE_TIME_SECS 7 +#define AR8XXX_DEFAULT_ARL_AGE_TIME 300 + /* Atheros specific MII registers */ #define MII_ATH_MMD_ADDR 0x0d #define MII_ATH_MMD_DATA 0x0e @@ -384,6 +387,8 @@ struct ar8xxx_chip { unsigned reg_port_stats_start; unsigned reg_port_stats_length; + unsigned reg_arl_ctrl; + int (*hw_init)(struct ar8xxx_priv *priv); void (*cleanup)(struct ar8xxx_priv *priv); @@ -449,6 +454,7 @@ struct ar8xxx_priv { u8 vlan_table[AR8X16_MAX_VLANS]; u8 vlan_tagged; u16 pvid[AR8X16_MAX_PORTS]; + int arl_age_time; /* mirroring */ bool mirror_rx; @@ -539,6 +545,14 @@ ar8xxx_sw_get_port_mib(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val); int +ar8xxx_sw_get_arl_age_time(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val); +int +ar8xxx_sw_set_arl_age_time(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val); +int ar8xxx_sw_get_arl_table(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val); diff --git a/target/linux/generic/files/drivers/net/phy/ar8327.c b/target/linux/generic/files/drivers/net/phy/ar8327.c index 02fd2e77bf..9c232382b5 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8327.c +++ b/target/linux/generic/files/drivers/net/phy/ar8327.c @@ -1275,6 +1275,13 @@ static const struct switch_attr ar8327_sw_attr_globals[] = { .max = AR8327_NUM_PORTS - 1 }, { + .type = SWITCH_TYPE_INT, + .name = "arl_age_time", + .description = "ARL age time (secs)", + .set = ar8xxx_sw_set_arl_age_time, + .get = ar8xxx_sw_get_arl_age_time, + }, + { .type = SWITCH_TYPE_STRING, .name = "arl_table", .description = "Get ARL table", @@ -1377,6 +1384,7 @@ const struct ar8xxx_chip ar8327_chip = { .reg_port_stats_start = 0x1000, .reg_port_stats_length = 0x100, + .reg_arl_ctrl = AR8327_REG_ARL_CTRL, .hw_init = ar8327_hw_init, .cleanup = ar8327_cleanup, @@ -1411,6 +1419,7 @@ const struct ar8xxx_chip ar8337_chip = { .reg_port_stats_start = 0x1000, .reg_port_stats_length = 0x100, + .reg_arl_ctrl = AR8327_REG_ARL_CTRL, .hw_init = ar8327_hw_init, .cleanup = ar8327_cleanup, diff --git a/target/linux/generic/files/drivers/net/phy/ar8327.h b/target/linux/generic/files/drivers/net/phy/ar8327.h index 4aca754bc8..e8dad35d11 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8327.h +++ b/target/linux/generic/files/drivers/net/phy/ar8327.h @@ -244,6 +244,8 @@ #define AR8327_VTU_FUNC1_VID_S 16 #define AR8327_VTU_FUNC1_BUSY BIT(31) +#define AR8327_REG_ARL_CTRL 0x0618 + #define AR8327_REG_FWD_CTRL0 0x620 #define AR8327_FWD_CTRL0_CPU_PORT_EN BIT(10) #define AR8327_FWD_CTRL0_MIRROR_PORT BITS(4, 4) |