Commit 0f5262e8 authored by Florian Fainelli's avatar Florian Fainelli Committed by Greg Kroah-Hartman

net: dsa: bcm_sf2: Fix ageing conditions and operation

[ Upstream commit 39797a27 ]

The comparison check between cur_hw_state and hw_state is currently
invalid because cur_hw_state is right shifted by G_MISTP_SHIFT, while
hw_state is not, so we end-up comparing bits 2:0 with bits 7:5, which is
going to cause an additional aging to occur. Fix this by not shifting
cur_hw_state while reading it, but instead, mask the value with the
appropriately shitfted bitmask.

The other problem with the fast-ageing process is that we did not set
the EN_AGE_DYNAMIC bit to request the ageing to occur for dynamically
learned MAC addresses. Finally, write back 0 to the FAST_AGE_CTRL
register to avoid leaving spurious bits sets from one operation to the
other.

Fixes: 12f460f2 ("net: dsa: bcm_sf2: add HW bridging support")
Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5008d77e
...@@ -417,7 +417,7 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port) ...@@ -417,7 +417,7 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port)
core_writel(priv, port, CORE_FAST_AGE_PORT); core_writel(priv, port, CORE_FAST_AGE_PORT);
reg = core_readl(priv, CORE_FAST_AGE_CTRL); reg = core_readl(priv, CORE_FAST_AGE_CTRL);
reg |= EN_AGE_PORT | FAST_AGE_STR_DONE; reg |= EN_AGE_PORT | EN_AGE_DYNAMIC | FAST_AGE_STR_DONE;
core_writel(priv, reg, CORE_FAST_AGE_CTRL); core_writel(priv, reg, CORE_FAST_AGE_CTRL);
do { do {
...@@ -431,6 +431,8 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port) ...@@ -431,6 +431,8 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port)
if (!timeout) if (!timeout)
return -ETIMEDOUT; return -ETIMEDOUT;
core_writel(priv, 0, CORE_FAST_AGE_CTRL);
return 0; return 0;
} }
...@@ -506,7 +508,7 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, ...@@ -506,7 +508,7 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port,
u32 reg; u32 reg;
reg = core_readl(priv, CORE_G_PCTL_PORT(port)); reg = core_readl(priv, CORE_G_PCTL_PORT(port));
cur_hw_state = reg >> G_MISTP_STATE_SHIFT; cur_hw_state = reg & (G_MISTP_STATE_MASK << G_MISTP_STATE_SHIFT);
switch (state) { switch (state) {
case BR_STATE_DISABLED: case BR_STATE_DISABLED:
...@@ -530,10 +532,12 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, ...@@ -530,10 +532,12 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port,
} }
/* Fast-age ARL entries if we are moving a port from Learning or /* Fast-age ARL entries if we are moving a port from Learning or
* Forwarding state to Disabled, Blocking or Listening state * Forwarding (cur_hw_state) state to Disabled, Blocking or Listening
* state (hw_state)
*/ */
if (cur_hw_state != hw_state) { if (cur_hw_state != hw_state) {
if (cur_hw_state & 4 && !(hw_state & 4)) { if (cur_hw_state >= G_MISTP_LEARN_STATE &&
hw_state <= G_MISTP_LISTEN_STATE) {
ret = bcm_sf2_sw_fast_age_port(ds, port); ret = bcm_sf2_sw_fast_age_port(ds, port);
if (ret) { if (ret) {
pr_err("%s: fast-ageing failed\n", __func__); pr_err("%s: fast-ageing failed\n", __func__);
......
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