From bdc0750191660af3ecefbc52327978af1cd93407 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 18 Jan 2015 00:53:53 +0000 Subject: ar8216: introduce enable_eee swconfig attribute to control 802.3az EEE per port Users reported network issues with AR8327 which turned out to be caused by EEE not working correctly with certain link partners (ticket 14597). The workaround was to disable EEE on all ports (changeset 41577). The issue was with certain link partners only, therefore this patch allows to control usage of EEE per port via swconfig. Still the default is to initially disable EEE on all ports. Successfully tested on a TL-WDR4900 (AR8327 rev.4) Signed-off-by: Heiner Kallweit SVN-Revision: 44021 --- .../linux/generic/files/drivers/net/phy/ar8327.c | 113 ++++++++++++++++++--- 1 file changed, 101 insertions(+), 12 deletions(-) (limited to 'target/linux/generic/files/drivers/net/phy/ar8327.c') diff --git a/target/linux/generic/files/drivers/net/phy/ar8327.c b/target/linux/generic/files/drivers/net/phy/ar8327.c index f6d07c1982..0971f80d50 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8327.c +++ b/target/linux/generic/files/drivers/net/phy/ar8327.c @@ -30,7 +30,6 @@ #include "ar8327.h" extern const struct ar8xxx_mib_desc ar8236_mibs[39]; -extern const struct switch_attr ar8xxx_sw_attr_port[2]; extern const struct switch_attr ar8xxx_sw_attr_vlan[1]; static u32 @@ -651,7 +650,9 @@ ar8327_cleanup(struct ar8xxx_priv *priv) static void ar8327_init_globals(struct ar8xxx_priv *priv) { + struct ar8327_data *data = priv->chip_data; u32 t; + int i; /* enable CPU port and disable mirror port */ t = AR8327_FWD_CTRL0_CPU_PORT_EN | @@ -672,14 +673,9 @@ ar8327_init_globals(struct ar8xxx_priv *priv) ar8xxx_reg_set(priv, AR8327_REG_MODULE_EN, AR8327_MODULE_EN_MIB); - /* Disable EEE on all ports due to stability issues */ - t = ar8xxx_read(priv, AR8327_REG_EEE_CTRL); - t |= AR8327_EEE_CTRL_DISABLE_PHY(0) | - AR8327_EEE_CTRL_DISABLE_PHY(1) | - AR8327_EEE_CTRL_DISABLE_PHY(2) | - AR8327_EEE_CTRL_DISABLE_PHY(3) | - AR8327_EEE_CTRL_DISABLE_PHY(4); - ar8xxx_write(priv, AR8327_REG_EEE_CTRL, t); + /* Disable EEE on all phy's due to stability issues */ + for (i = 0; i < AR8XXX_NUM_PHYS; i++) + data->eee[i] = false; } static void @@ -892,6 +888,73 @@ ar8327_set_mirror_regs(struct ar8xxx_priv *priv) AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN); } +static int +ar8327_sw_set_eee(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + struct ar8327_data *data = priv->chip_data; + int port = val->port_vlan; + int phy; + + if (port >= dev->ports) + return -EINVAL; + if (port == 0 || port == 6) + return -EOPNOTSUPP; + + phy = port - 1; + + data->eee[phy] = !!(val->value.i); + + return 0; +} + +static int +ar8327_sw_get_eee(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + const struct ar8327_data *data = priv->chip_data; + int port = val->port_vlan; + int phy; + + if (port >= dev->ports) + return -EINVAL; + if (port == 0 || port == 6) + return -EOPNOTSUPP; + + phy = port - 1; + + val->value.i = data->eee[phy]; + + return 0; +} + +static int +ar8327_sw_hw_apply(struct switch_dev *dev) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + const struct ar8327_data *data = priv->chip_data; + int ret, i; + + ret = ar8xxx_sw_hw_apply(dev); + if (ret) + return ret; + + for (i=0; i < AR8XXX_NUM_PHYS; i++) { + if (data->eee[i]) + ar8xxx_reg_clear(priv, AR8327_REG_EEE_CTRL, + AR8327_EEE_CTRL_DISABLE_PHY(i)); + else + ar8xxx_reg_set(priv, AR8327_REG_EEE_CTRL, + AR8327_EEE_CTRL_DISABLE_PHY(i)); + } + + return 0; +} + static const struct switch_attr ar8327_sw_attr_globals[] = { { .type = SWITCH_TYPE_INT, @@ -941,14 +1004,38 @@ static const struct switch_attr ar8327_sw_attr_globals[] = { }, }; +static const struct switch_attr ar8327_sw_attr_port[] = { + { + .type = SWITCH_TYPE_NOVAL, + .name = "reset_mib", + .description = "Reset single port MIB counters", + .set = ar8xxx_sw_set_port_reset_mib, + }, + { + .type = SWITCH_TYPE_STRING, + .name = "mib", + .description = "Get port's MIB counters", + .set = NULL, + .get = ar8xxx_sw_get_port_mib, + }, + { + .type = SWITCH_TYPE_INT, + .name = "enable_eee", + .description = "Enable EEE PHY sleep mode", + .set = ar8327_sw_set_eee, + .get = ar8327_sw_get_eee, + .max = 1, + }, +}; + static const struct switch_dev_ops ar8327_sw_ops = { .attr_global = { .attr = ar8327_sw_attr_globals, .n_attr = ARRAY_SIZE(ar8327_sw_attr_globals), }, .attr_port = { - .attr = ar8xxx_sw_attr_port, - .n_attr = ARRAY_SIZE(ar8xxx_sw_attr_port), + .attr = ar8327_sw_attr_port, + .n_attr = ARRAY_SIZE(ar8327_sw_attr_port), }, .attr_vlan = { .attr = ar8xxx_sw_attr_vlan, @@ -958,7 +1045,7 @@ static const struct switch_dev_ops ar8327_sw_ops = { .set_port_pvid = ar8xxx_sw_set_pvid, .get_vlan_ports = ar8327_sw_get_ports, .set_vlan_ports = ar8327_sw_set_ports, - .apply_config = ar8xxx_sw_hw_apply, + .apply_config = ar8327_sw_hw_apply, .reset_switch = ar8xxx_sw_reset_switch, .get_port_link = ar8xxx_sw_get_port_link, }; @@ -987,6 +1074,7 @@ const struct ar8xxx_chip ar8327_chip = { .vtu_load_vlan = ar8327_vtu_load_vlan, .phy_fixup = ar8327_phy_fixup, .set_mirror_regs = ar8327_set_mirror_regs, + .sw_hw_apply = ar8327_sw_hw_apply, .num_mibs = ARRAY_SIZE(ar8236_mibs), .mib_decs = ar8236_mibs, @@ -1017,6 +1105,7 @@ const struct ar8xxx_chip ar8337_chip = { .vtu_load_vlan = ar8327_vtu_load_vlan, .phy_fixup = ar8327_phy_fixup, .set_mirror_regs = ar8327_set_mirror_regs, + .sw_hw_apply = ar8327_sw_hw_apply, .num_mibs = ARRAY_SIZE(ar8236_mibs), .mib_decs = ar8236_mibs, -- cgit v1.2.3