From e893de1ba1d39e78750ffadf7191aef8133c8fe8 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 15 Mar 2017 15:53:48 -0400 Subject: [PATCH 1/3] net: dsa: dsa_fastest_ageing_time return unsigned The ageing time is defined as unsigned int, so make dsa_fastest_ageing_time return an unsigned int instead of int. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/slave.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index c34872e1febc4..cec47e8435705 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -419,8 +419,8 @@ static int dsa_slave_vlan_filtering(struct net_device *dev, return 0; } -static int dsa_fastest_ageing_time(struct dsa_switch *ds, - unsigned int ageing_time) +static unsigned int dsa_fastest_ageing_time(struct dsa_switch *ds, + unsigned int ageing_time) { int i; From 0f3da6afeef1f63c7254965253f7e6535dc7910c Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 15 Mar 2017 15:53:49 -0400 Subject: [PATCH 2/3] net: dsa: check out-of-range ageing time value If a DSA switch driver cannot program an ageing time value due to it being out-of-range, switchdev will raise a stack trace before failing. To fix this, add ageing_time_min and ageing_time_max members to the dsa_switch in order for the switch drivers to optionally specify their supported ageing time limits. The DSA core will now check for provided ageing time limits and return -ERANGE from the switchdev prepare phase if the value is out-of-range. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- include/net/dsa.h | 4 ++++ net/dsa/slave.c | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index bf0e42c2a6f78..e42897fd7a965 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -233,6 +233,10 @@ struct dsa_switch { u32 phys_mii_mask; struct mii_bus *slave_mii_bus; + /* Ageing Time limits in msecs */ + unsigned int ageing_time_min; + unsigned int ageing_time_max; + /* Dynamically allocated ports, keep last */ size_t num_ports; struct dsa_port ports[]; diff --git a/net/dsa/slave.c b/net/dsa/slave.c index cec47e8435705..78128acfbf633 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -443,9 +443,13 @@ static int dsa_slave_ageing_time(struct net_device *dev, unsigned long ageing_jiffies = clock_t_to_jiffies(attr->u.ageing_time); unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies); - /* bridge skips -EOPNOTSUPP, so skip the prepare phase */ - if (switchdev_trans_ph_prepare(trans)) + if (switchdev_trans_ph_prepare(trans)) { + if (ds->ageing_time_min && ageing_time < ds->ageing_time_min) + return -ERANGE; + if (ds->ageing_time_max && ageing_time > ds->ageing_time_max) + return -ERANGE; return 0; + } /* Keep the fastest ageing time in case of multiple bridges */ p->dp->ageing_time = ageing_time; From 9ff74f249db8c80f13568460e26d168f5c6d55cd Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 15 Mar 2017 15:53:50 -0400 Subject: [PATCH 3/3] net: dsa: mv88e6xxx: specify ageing time limits Now that DSA has ageing time limits, specify them when registering a switch so that out-of-range values are handled correctly by the core. Signed-off-by: Vivien Didelot Reported-by: Jason Cobham Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 3354f99df378f..2bca297d92963 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4253,6 +4253,8 @@ static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip) ds->priv = chip; ds->ops = &mv88e6xxx_switch_ops; + ds->ageing_time_min = chip->info->age_time_coeff; + ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; dev_set_drvdata(dev, ds);