aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa/slave.c
diff options
context:
space:
mode:
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>2016-07-18 20:45:38 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-19 22:42:01 -0400
commit34a79f63bbe49c888f95e75dd759685a238556b6 (patch)
tree1ca00fd6bc27ee95e40434e2c3a6e0d5b33daf4d /net/dsa/slave.c
parent8ec61c7f7c6c75943e8c785729bd8de3440d158c (diff)
net: dsa: support switchdev ageing time attr
Add a new function for DSA drivers to handle the switchdev SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME attribute. The ageing time is passed as milliseconds. Also because we can have multiple logical bridges on top of a physical switch and ageing time are switch-wide, call the driver function with the fastest ageing time in use on the chip instead of the requested one. Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa/slave.c')
-rw-r--r--net/dsa/slave.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 7236eb26dc97..fc9196745225 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -333,6 +333,44 @@ static int dsa_slave_vlan_filtering(struct net_device *dev,
333 return 0; 333 return 0;
334} 334}
335 335
336static int dsa_fastest_ageing_time(struct dsa_switch *ds,
337 unsigned int ageing_time)
338{
339 int i;
340
341 for (i = 0; i < DSA_MAX_PORTS; ++i) {
342 struct dsa_port *dp = &ds->ports[i];
343
344 if (dp && dp->ageing_time && dp->ageing_time < ageing_time)
345 ageing_time = dp->ageing_time;
346 }
347
348 return ageing_time;
349}
350
351static int dsa_slave_ageing_time(struct net_device *dev,
352 const struct switchdev_attr *attr,
353 struct switchdev_trans *trans)
354{
355 struct dsa_slave_priv *p = netdev_priv(dev);
356 struct dsa_switch *ds = p->parent;
357 unsigned long ageing_jiffies = clock_t_to_jiffies(attr->u.ageing_time);
358 unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies);
359
360 /* bridge skips -EOPNOTSUPP, so skip the prepare phase */
361 if (switchdev_trans_ph_prepare(trans))
362 return 0;
363
364 /* Keep the fastest ageing time in case of multiple bridges */
365 ds->ports[p->port].ageing_time = ageing_time;
366 ageing_time = dsa_fastest_ageing_time(ds, ageing_time);
367
368 if (ds->drv->set_ageing_time)
369 return ds->drv->set_ageing_time(ds, ageing_time);
370
371 return 0;
372}
373
336static int dsa_slave_port_attr_set(struct net_device *dev, 374static int dsa_slave_port_attr_set(struct net_device *dev,
337 const struct switchdev_attr *attr, 375 const struct switchdev_attr *attr,
338 struct switchdev_trans *trans) 376 struct switchdev_trans *trans)
@@ -346,6 +384,9 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
346 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: 384 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
347 ret = dsa_slave_vlan_filtering(dev, attr, trans); 385 ret = dsa_slave_vlan_filtering(dev, attr, trans);
348 break; 386 break;
387 case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
388 ret = dsa_slave_ageing_time(dev, attr, trans);
389 break;
349 default: 390 default:
350 ret = -EOPNOTSUPP; 391 ret = -EOPNOTSUPP;
351 break; 392 break;