Skip to content

Commit

Permalink
Merge branch 'dsa-port-fast-ageing'
Browse files Browse the repository at this point in the history
Vivien Didelot says:

====================
net: dsa: add port fast ageing

Today the DSA drivers are in charge of flushing the MAC addresses
associated to a port when its STP state changes from Learning or
Forwarding, to Disabled or Blocking or Listening.

This makes the drivers more complex and hides this generic switch logic.

This patchset introduces a new optional port_fast_age operation to
dsa_switch_ops, to move this logic to the DSA layer and keep drivers
simple. b53 and mv88e6xxx are updated accordingly.
====================

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 23, 2016
2 parents e397867 + 749efcb commit dd5a300
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 49 deletions.
31 changes: 11 additions & 20 deletions drivers/net/dsa/b53/b53_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1402,16 +1402,12 @@ static void b53_br_leave(struct dsa_switch *ds, int port)
}
}

static void b53_br_set_stp_state(struct dsa_switch *ds, int port,
u8 state)
static void b53_br_set_stp_state(struct dsa_switch *ds, int port, u8 state)
{
struct b53_device *dev = ds->priv;
u8 hw_state, cur_hw_state;
u8 hw_state;
u8 reg;

b53_read8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), &reg);
cur_hw_state = reg & PORT_CTRL_STP_STATE_MASK;

switch (state) {
case BR_STATE_DISABLED:
hw_state = PORT_CTRL_DIS_STATE;
Expand All @@ -1433,26 +1429,20 @@ static void b53_br_set_stp_state(struct dsa_switch *ds, int port,
return;
}

/* Fast-age ARL entries if we are moving a port from Learning or
* Forwarding (cur_hw_state) state to Disabled, Blocking or Listening
* state (hw_state)
*/
if (cur_hw_state != hw_state) {
if (cur_hw_state >= PORT_CTRL_LEARN_STATE &&
hw_state <= PORT_CTRL_LISTEN_STATE) {
if (b53_fast_age_port(dev, port)) {
dev_err(ds->dev, "fast ageing failed\n");
return;
}
}
}

b53_read8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), &reg);
reg &= ~PORT_CTRL_STP_STATE_MASK;
reg |= hw_state;
b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), reg);
}

static void b53_br_fast_age(struct dsa_switch *ds, int port)
{
struct b53_device *dev = ds->priv;

if (b53_fast_age_port(dev, port))
dev_err(ds->dev, "fast ageing failed\n");
}

static enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds)
{
return DSA_TAG_PROTO_NONE;
Expand All @@ -1472,6 +1462,7 @@ static struct dsa_switch_ops b53_switch_ops = {
.port_bridge_join = b53_br_join,
.port_bridge_leave = b53_br_leave,
.port_stp_state_set = b53_br_set_stp_state,
.port_fast_age = b53_br_fast_age,
.port_vlan_filtering = b53_vlan_filtering,
.port_vlan_prepare = b53_vlan_prepare,
.port_vlan_add = b53_vlan_add,
Expand Down
45 changes: 23 additions & 22 deletions drivers/net/dsa/mv88e6xxx/chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -1133,31 +1133,18 @@ static int _mv88e6xxx_port_state(struct mv88e6xxx_chip *chip, int port,

oldstate = reg & PORT_CONTROL_STATE_MASK;

if (oldstate != state) {
/* Flush forwarding database if we're moving a port
* from Learning or Forwarding state to Disabled or
* Blocking or Listening state.
*/
if ((oldstate == PORT_CONTROL_STATE_LEARNING ||
oldstate == PORT_CONTROL_STATE_FORWARDING) &&
(state == PORT_CONTROL_STATE_DISABLED ||
state == PORT_CONTROL_STATE_BLOCKING)) {
err = _mv88e6xxx_atu_remove(chip, 0, port, false);
if (err)
return err;
}
reg &= ~PORT_CONTROL_STATE_MASK;
reg |= state;

reg = (reg & ~PORT_CONTROL_STATE_MASK) | state;
err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
if (err)
return err;
err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
if (err)
return err;

netdev_dbg(ds->ports[port].netdev, "PortState %s (was %s)\n",
mv88e6xxx_port_state_names[state],
mv88e6xxx_port_state_names[oldstate]);
}
netdev_dbg(ds->ports[port].netdev, "PortState %s (was %s)\n",
mv88e6xxx_port_state_names[state],
mv88e6xxx_port_state_names[oldstate]);

return err;
return 0;
}

static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port)
Expand Down Expand Up @@ -1232,6 +1219,19 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
mv88e6xxx_port_state_names[stp_state]);
}

static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
{
struct mv88e6xxx_chip *chip = ds->priv;
int err;

mutex_lock(&chip->reg_lock);
err = _mv88e6xxx_atu_remove(chip, 0, port, false);
mutex_unlock(&chip->reg_lock);

if (err)
netdev_err(ds->ports[port].netdev, "failed to flush ATU\n");
}

static int _mv88e6xxx_port_pvid(struct mv88e6xxx_chip *chip, int port,
u16 *new, u16 *old)
{
Expand Down Expand Up @@ -3684,6 +3684,7 @@ static struct dsa_switch_ops mv88e6xxx_switch_ops = {
.port_bridge_join = mv88e6xxx_port_bridge_join,
.port_bridge_leave = mv88e6xxx_port_bridge_leave,
.port_stp_state_set = mv88e6xxx_port_stp_state_set,
.port_fast_age = mv88e6xxx_port_fast_age,
.port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
.port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
.port_vlan_add = mv88e6xxx_port_vlan_add,
Expand Down
2 changes: 2 additions & 0 deletions include/net/dsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ struct dsa_port {
struct net_device *netdev;
struct device_node *dn;
unsigned int ageing_time;
u8 stp_state;
};

struct dsa_switch {
Expand Down Expand Up @@ -339,6 +340,7 @@ struct dsa_switch_ops {
void (*port_bridge_leave)(struct dsa_switch *ds, int port);
void (*port_stp_state_set)(struct dsa_switch *ds, int port,
u8 state);
void (*port_fast_age)(struct dsa_switch *ds, int port);

/*
* VLAN support
Expand Down
35 changes: 28 additions & 7 deletions net/dsa/slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,30 @@ static inline bool dsa_port_is_bridged(struct dsa_slave_priv *p)
return !!p->bridge_dev;
}

static void dsa_port_set_stp_state(struct dsa_switch *ds, int port, u8 state)
{
struct dsa_port *dp = &ds->ports[port];

if (ds->ops->port_stp_state_set)
ds->ops->port_stp_state_set(ds, port, state);

if (ds->ops->port_fast_age) {
/* Fast age FDB entries or flush appropriate forwarding database
* for the given port, if we are moving it from Learning or
* Forwarding state, to Disabled or Blocking or Listening state.
*/

if ((dp->stp_state == BR_STATE_LEARNING ||
dp->stp_state == BR_STATE_FORWARDING) &&
(state == BR_STATE_DISABLED ||
state == BR_STATE_BLOCKING ||
state == BR_STATE_LISTENING))
ds->ops->port_fast_age(ds, port);
}

dp->stp_state = state;
}

static int dsa_slave_open(struct net_device *dev)
{
struct dsa_slave_priv *p = netdev_priv(dev);
Expand Down Expand Up @@ -104,8 +128,7 @@ static int dsa_slave_open(struct net_device *dev)
goto clear_promisc;
}

if (ds->ops->port_stp_state_set)
ds->ops->port_stp_state_set(ds, p->port, stp_state);
dsa_port_set_stp_state(ds, p->port, stp_state);

if (p->phy)
phy_start(p->phy);
Expand Down Expand Up @@ -147,8 +170,7 @@ static int dsa_slave_close(struct net_device *dev)
if (ds->ops->port_disable)
ds->ops->port_disable(ds, p->port, p->phy);

if (ds->ops->port_stp_state_set)
ds->ops->port_stp_state_set(ds, p->port, BR_STATE_DISABLED);
dsa_port_set_stp_state(ds, p->port, BR_STATE_DISABLED);

return 0;
}
Expand Down Expand Up @@ -354,7 +376,7 @@ static int dsa_slave_stp_state_set(struct net_device *dev,
if (switchdev_trans_ph_prepare(trans))
return ds->ops->port_stp_state_set ? 0 : -EOPNOTSUPP;

ds->ops->port_stp_state_set(ds, p->port, attr->u.stp_state);
dsa_port_set_stp_state(ds, p->port, attr->u.stp_state);

return 0;
}
Expand Down Expand Up @@ -556,8 +578,7 @@ static void dsa_slave_bridge_port_leave(struct net_device *dev)
/* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
* so allow it to be in BR_STATE_FORWARDING to be kept functional
*/
if (ds->ops->port_stp_state_set)
ds->ops->port_stp_state_set(ds, p->port, BR_STATE_FORWARDING);
dsa_port_set_stp_state(ds, p->port, BR_STATE_FORWARDING);
}

static int dsa_slave_port_attr_get(struct net_device *dev,
Expand Down

0 comments on commit dd5a300

Please sign in to comment.