diff options
author | Vivien Didelot <vivien.didelot@savoirfairelinux.com> | 2016-07-18 20:45:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-19 22:42:01 -0400 |
commit | 34a79f63bbe49c888f95e75dd759685a238556b6 (patch) | |
tree | 1ca00fd6bc27ee95e40434e2c3a6e0d5b33daf4d /net/dsa/slave.c | |
parent | 8ec61c7f7c6c75943e8c785729bd8de3440d158c (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.c | 41 |
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 | ||
336 | static 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 | |||
351 | static 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 | |||
336 | static int dsa_slave_port_attr_set(struct net_device *dev, | 374 | static 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; |