From a40c175b4a4a2c6f7e111ed6dc0186c75287dff0 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 19 May 2017 17:00:44 -0400 Subject: net: dsa: move port state setters Add a new port.c file to hold all DSA port-wide logic. This patch moves in the code which sets a port state. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/port.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 net/dsa/port.c (limited to 'net/dsa/port.c') diff --git a/net/dsa/port.c b/net/dsa/port.c new file mode 100644 index 000000000000..6cc4704190fd --- /dev/null +++ b/net/dsa/port.c @@ -0,0 +1,55 @@ +/* + * Handling of a single switch port + * + * Copyright (c) 2017 Savoir-faire Linux Inc. + * Vivien Didelot + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +#include "dsa_priv.h" + +int dsa_port_set_state(struct dsa_port *dp, u8 state, + struct switchdev_trans *trans) +{ + struct dsa_switch *ds = dp->ds; + int port = dp->index; + + if (switchdev_trans_ph_prepare(trans)) + return ds->ops->port_stp_state_set ? 0 : -EOPNOTSUPP; + + 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; + + return 0; +} + +void dsa_port_set_state_now(struct dsa_port *dp, u8 state) +{ + int err; + + err = dsa_port_set_state(dp, state, NULL); + if (err) + pr_err("DSA: failed to set STP state %u (%d)\n", state, err); +} -- cgit v1.2.3 From cfbed329beb2e44562c2c6b292142e3c9adc3203 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 19 May 2017 17:00:45 -0400 Subject: net: dsa: move bridging routines Move the DSA port code which bridges a port in port.c, where it belongs. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 2 ++ net/dsa/port.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/dsa/slave.c | 57 ----------------------------------------------------- 3 files changed, 60 insertions(+), 57 deletions(-) (limited to 'net/dsa/port.c') diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index cda218cd9b05..f0b6cd3c8a65 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -64,6 +64,8 @@ void dsa_legacy_unregister(void); int dsa_port_set_state(struct dsa_port *dp, u8 state, struct switchdev_trans *trans); void dsa_port_set_state_now(struct dsa_port *dp, u8 state); +int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br); +void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br); /* slave.c */ extern const struct dsa_device_ops notag_netdev_ops; diff --git a/net/dsa/port.c b/net/dsa/port.c index 6cc4704190fd..da8577fb3d07 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -11,9 +11,20 @@ */ #include +#include #include "dsa_priv.h" +static int dsa_port_notify(struct dsa_port *dp, unsigned long e, void *v) +{ + struct raw_notifier_head *nh = &dp->ds->dst->nh; + int err; + + err = raw_notifier_call_chain(nh, e, v); + + return notifier_to_errno(err); +} + int dsa_port_set_state(struct dsa_port *dp, u8 state, struct switchdev_trans *trans) { @@ -53,3 +64,50 @@ void dsa_port_set_state_now(struct dsa_port *dp, u8 state) if (err) pr_err("DSA: failed to set STP state %u (%d)\n", state, err); } + +int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) +{ + struct dsa_notifier_bridge_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .br = br, + }; + int err; + + /* Here the port is already bridged. Reflect the current configuration + * so that drivers can program their chips accordingly. + */ + dp->bridge_dev = br; + + err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_JOIN, &info); + + /* The bridging is rolled back on error */ + if (err) + dp->bridge_dev = NULL; + + return err; +} + +void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br) +{ + struct dsa_notifier_bridge_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .br = br, + }; + int err; + + /* Here the port is already unbridged. Reflect the current configuration + * so that drivers can program their chips accordingly. + */ + dp->bridge_dev = NULL; + + err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_LEAVE, &info); + if (err) + pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n"); + + /* 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 + */ + dsa_port_set_state_now(dp, BR_STATE_FORWARDING); +} diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 2c57c7205aa3..ab298c41b8e7 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -27,16 +27,6 @@ static bool dsa_slave_dev_check(struct net_device *dev); -static int dsa_port_notify(struct dsa_port *dp, unsigned long e, void *v) -{ - struct raw_notifier_head *nh = &dp->ds->dst->nh; - int err; - - err = raw_notifier_call_chain(nh, e, v); - - return notifier_to_errno(err); -} - /* slave mii_bus handling ***************************************************/ static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg) { @@ -514,53 +504,6 @@ static int dsa_slave_port_obj_dump(struct net_device *dev, return err; } -static int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) -{ - struct dsa_notifier_bridge_info info = { - .sw_index = dp->ds->index, - .port = dp->index, - .br = br, - }; - int err; - - /* Here the port is already bridged. Reflect the current configuration - * so that drivers can program their chips accordingly. - */ - dp->bridge_dev = br; - - err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_JOIN, &info); - - /* The bridging is rolled back on error */ - if (err) - dp->bridge_dev = NULL; - - return err; -} - -static void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br) -{ - struct dsa_notifier_bridge_info info = { - .sw_index = dp->ds->index, - .port = dp->index, - .br = br, - }; - int err; - - /* Here the port is already unbridged. Reflect the current configuration - * so that drivers can program their chips accordingly. - */ - dp->bridge_dev = NULL; - - err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_LEAVE, &info); - if (err) - pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n"); - - /* 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 - */ - dsa_port_set_state_now(dp, BR_STATE_FORWARDING); -} - static int dsa_slave_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { -- cgit v1.2.3 From 4d61d3043bef7b61e7c30276488ff310bee0d897 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 19 May 2017 17:00:46 -0400 Subject: net: dsa: move VLAN filtering setter Move the DSA port code which sets VLAN filtering on a port in port.c, where it belongs. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 2 ++ net/dsa/port.c | 16 ++++++++++++++++ net/dsa/slave.c | 16 ---------------- 3 files changed, 18 insertions(+), 16 deletions(-) (limited to 'net/dsa/port.c') diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index f0b6cd3c8a65..c145223247c5 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -66,6 +66,8 @@ int dsa_port_set_state(struct dsa_port *dp, u8 state, void dsa_port_set_state_now(struct dsa_port *dp, u8 state); int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br); void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br); +int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, + struct switchdev_trans *trans); /* slave.c */ extern const struct dsa_device_ops notag_netdev_ops; diff --git a/net/dsa/port.c b/net/dsa/port.c index da8577fb3d07..c9f95aaf25f1 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -111,3 +111,19 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br) */ dsa_port_set_state_now(dp, BR_STATE_FORWARDING); } + +int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, + struct switchdev_trans *trans) +{ + struct dsa_switch *ds = dp->ds; + + /* bridge skips -EOPNOTSUPP, so skip the prepare phase */ + if (switchdev_trans_ph_prepare(trans)) + return 0; + + if (ds->ops->port_vlan_filtering) + return ds->ops->port_vlan_filtering(ds, dp->index, + vlan_filtering); + + return 0; +} diff --git a/net/dsa/slave.c b/net/dsa/slave.c index ab298c41b8e7..32e7e78313ba 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -338,22 +338,6 @@ static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EOPNOTSUPP; } -static int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, - struct switchdev_trans *trans) -{ - struct dsa_switch *ds = dp->ds; - - /* bridge skips -EOPNOTSUPP, so skip the prepare phase */ - if (switchdev_trans_ph_prepare(trans)) - return 0; - - if (ds->ops->port_vlan_filtering) - return ds->ops->port_vlan_filtering(ds, dp->index, - vlan_filtering); - - return 0; -} - static unsigned int dsa_fastest_ageing_time(struct dsa_switch *ds, unsigned int ageing_time) { -- cgit v1.2.3 From d87bd94e1c2006c1bb1d717020116940f9d0735a Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 19 May 2017 17:00:47 -0400 Subject: net: dsa: move ageing time setter Move the DSA port code which sets a port ageing time in port.c, where it belongs. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 2 ++ net/dsa/port.c | 40 ++++++++++++++++++++++++++++++++++++++++ net/dsa/slave.c | 40 ---------------------------------------- 3 files changed, 42 insertions(+), 40 deletions(-) (limited to 'net/dsa/port.c') diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index c145223247c5..b0f9837bf5ed 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -68,6 +68,8 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br); void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br); int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, struct switchdev_trans *trans); +int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, + struct switchdev_trans *trans); /* slave.c */ extern const struct dsa_device_ops notag_netdev_ops; diff --git a/net/dsa/port.c b/net/dsa/port.c index c9f95aaf25f1..3382fdc07a11 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -127,3 +127,43 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, return 0; } + +static unsigned int dsa_fastest_ageing_time(struct dsa_switch *ds, + unsigned int ageing_time) +{ + int i; + + for (i = 0; i < ds->num_ports; ++i) { + struct dsa_port *dp = &ds->ports[i]; + + if (dp->ageing_time && dp->ageing_time < ageing_time) + ageing_time = dp->ageing_time; + } + + return ageing_time; +} + +int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, + struct switchdev_trans *trans) +{ + unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock); + unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies); + struct dsa_switch *ds = dp->ds; + + 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 */ + dp->ageing_time = ageing_time; + ageing_time = dsa_fastest_ageing_time(ds, ageing_time); + + if (ds->ops->set_ageing_time) + return ds->ops->set_ageing_time(ds, ageing_time); + + return 0; +} diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 32e7e78313ba..1b0f396c4314 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -338,46 +338,6 @@ static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EOPNOTSUPP; } -static unsigned int dsa_fastest_ageing_time(struct dsa_switch *ds, - unsigned int ageing_time) -{ - int i; - - for (i = 0; i < ds->num_ports; ++i) { - struct dsa_port *dp = &ds->ports[i]; - - if (dp->ageing_time && dp->ageing_time < ageing_time) - ageing_time = dp->ageing_time; - } - - return ageing_time; -} - -static int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, - struct switchdev_trans *trans) -{ - unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock); - unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies); - struct dsa_switch *ds = dp->ds; - - 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 */ - dp->ageing_time = ageing_time; - ageing_time = dsa_fastest_ageing_time(ds, ageing_time); - - if (ds->ops->set_ageing_time) - return ds->ops->set_ageing_time(ds, ageing_time); - - return 0; -} - static int dsa_slave_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr, struct switchdev_trans *trans) -- cgit v1.2.3 From d1cffff008dc2f238bfd0700c0f5027980089510 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 19 May 2017 17:00:48 -0400 Subject: net: dsa: move FDB handlers Move the DSA port code which handles FDB objects in port.c, where it belongs. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 7 +++++++ net/dsa/port.c | 40 ++++++++++++++++++++++++++++++++++++++++ net/dsa/slave.c | 42 ------------------------------------------ 3 files changed, 47 insertions(+), 42 deletions(-) (limited to 'net/dsa/port.c') diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index b0f9837bf5ed..d003a2554c7a 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -70,6 +70,13 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, struct switchdev_trans *trans); int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, struct switchdev_trans *trans); +int dsa_port_fdb_add(struct dsa_port *dp, + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans); +int dsa_port_fdb_del(struct dsa_port *dp, + const struct switchdev_obj_port_fdb *fdb); +int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb, + switchdev_obj_dump_cb_t *cb); /* slave.c */ extern const struct dsa_device_ops notag_netdev_ops; diff --git a/net/dsa/port.c b/net/dsa/port.c index 3382fdc07a11..18ec6d432152 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -167,3 +167,43 @@ int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, return 0; } + +int dsa_port_fdb_add(struct dsa_port *dp, + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans) +{ + struct dsa_switch *ds = dp->ds; + + if (switchdev_trans_ph_prepare(trans)) { + if (!ds->ops->port_fdb_prepare || !ds->ops->port_fdb_add) + return -EOPNOTSUPP; + + return ds->ops->port_fdb_prepare(ds, dp->index, fdb, trans); + } + + ds->ops->port_fdb_add(ds, dp->index, fdb, trans); + + return 0; +} + +int dsa_port_fdb_del(struct dsa_port *dp, + const struct switchdev_obj_port_fdb *fdb) +{ + struct dsa_switch *ds = dp->ds; + + if (ds->ops->port_fdb_del) + return -EOPNOTSUPP; + + return ds->ops->port_fdb_del(ds, dp->index, fdb); +} + +int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb, + switchdev_obj_dump_cb_t *cb) +{ + struct dsa_switch *ds = dp->ds; + + if (ds->ops->port_fdb_dump) + return ds->ops->port_fdb_dump(ds, dp->index, fdb, cb); + + return -EOPNOTSUPP; +} diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 1b0f396c4314..d9b7bf759f44 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -245,48 +245,6 @@ static int dsa_port_vlan_dump(struct dsa_port *dp, return -EOPNOTSUPP; } -static int dsa_port_fdb_add(struct dsa_port *dp, - const struct switchdev_obj_port_fdb *fdb, - struct switchdev_trans *trans) -{ - struct dsa_switch *ds = dp->ds; - - if (switchdev_trans_ph_prepare(trans)) { - if (!ds->ops->port_fdb_prepare || !ds->ops->port_fdb_add) - return -EOPNOTSUPP; - - return ds->ops->port_fdb_prepare(ds, dp->index, fdb, trans); - } - - ds->ops->port_fdb_add(ds, dp->index, fdb, trans); - - return 0; -} - -static int dsa_port_fdb_del(struct dsa_port *dp, - const struct switchdev_obj_port_fdb *fdb) -{ - struct dsa_switch *ds = dp->ds; - int ret = -EOPNOTSUPP; - - if (ds->ops->port_fdb_del) - ret = ds->ops->port_fdb_del(ds, dp->index, fdb); - - return ret; -} - -static int dsa_port_fdb_dump(struct dsa_port *dp, - struct switchdev_obj_port_fdb *fdb, - switchdev_obj_dump_cb_t *cb) -{ - struct dsa_switch *ds = dp->ds; - - if (ds->ops->port_fdb_dump) - return ds->ops->port_fdb_dump(ds, dp->index, fdb, cb); - - return -EOPNOTSUPP; -} - static int dsa_port_mdb_add(struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb, struct switchdev_trans *trans) -- cgit v1.2.3 From 3a9afea37e298f4989629553d44b9bf50dc46125 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 19 May 2017 17:00:49 -0400 Subject: net: dsa: move MDB handlers Move the DSA port code which handles MDB objects in port.c, where it belongs. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 7 +++++++ net/dsa/port.c | 40 ++++++++++++++++++++++++++++++++++++++++ net/dsa/slave.c | 41 ----------------------------------------- 3 files changed, 47 insertions(+), 41 deletions(-) (limited to 'net/dsa/port.c') diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index d003a2554c7a..c2a595036746 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -77,6 +77,13 @@ int dsa_port_fdb_del(struct dsa_port *dp, const struct switchdev_obj_port_fdb *fdb); int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb, switchdev_obj_dump_cb_t *cb); +int dsa_port_mdb_add(struct dsa_port *dp, + const struct switchdev_obj_port_mdb *mdb, + struct switchdev_trans *trans); +int dsa_port_mdb_del(struct dsa_port *dp, + const struct switchdev_obj_port_mdb *mdb); +int dsa_port_mdb_dump(struct dsa_port *dp, struct switchdev_obj_port_mdb *mdb, + switchdev_obj_dump_cb_t *cb); /* slave.c */ extern const struct dsa_device_ops notag_netdev_ops; diff --git a/net/dsa/port.c b/net/dsa/port.c index 18ec6d432152..4ed0124a8d4b 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -207,3 +207,43 @@ int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb, return -EOPNOTSUPP; } + +int dsa_port_mdb_add(struct dsa_port *dp, + const struct switchdev_obj_port_mdb *mdb, + struct switchdev_trans *trans) +{ + struct dsa_switch *ds = dp->ds; + + if (switchdev_trans_ph_prepare(trans)) { + if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add) + return -EOPNOTSUPP; + + return ds->ops->port_mdb_prepare(ds, dp->index, mdb, trans); + } + + ds->ops->port_mdb_add(ds, dp->index, mdb, trans); + + return 0; +} + +int dsa_port_mdb_del(struct dsa_port *dp, + const struct switchdev_obj_port_mdb *mdb) +{ + struct dsa_switch *ds = dp->ds; + + if (ds->ops->port_mdb_del) + return ds->ops->port_mdb_del(ds, dp->index, mdb); + + return -EOPNOTSUPP; +} + +int dsa_port_mdb_dump(struct dsa_port *dp, struct switchdev_obj_port_mdb *mdb, + switchdev_obj_dump_cb_t *cb) +{ + struct dsa_switch *ds = dp->ds; + + if (ds->ops->port_mdb_dump) + return ds->ops->port_mdb_dump(ds, dp->index, mdb, cb); + + return -EOPNOTSUPP; +} diff --git a/net/dsa/slave.c b/net/dsa/slave.c index d9b7bf759f44..9adcb8267d9a 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -245,47 +245,6 @@ static int dsa_port_vlan_dump(struct dsa_port *dp, return -EOPNOTSUPP; } -static int dsa_port_mdb_add(struct dsa_port *dp, - const struct switchdev_obj_port_mdb *mdb, - struct switchdev_trans *trans) -{ - struct dsa_switch *ds = dp->ds; - - if (switchdev_trans_ph_prepare(trans)) { - if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add) - return -EOPNOTSUPP; - - return ds->ops->port_mdb_prepare(ds, dp->index, mdb, trans); - } - - ds->ops->port_mdb_add(ds, dp->index, mdb, trans); - - return 0; -} - -static int dsa_port_mdb_del(struct dsa_port *dp, - const struct switchdev_obj_port_mdb *mdb) -{ - struct dsa_switch *ds = dp->ds; - - if (ds->ops->port_mdb_del) - return ds->ops->port_mdb_del(ds, dp->index, mdb); - - return -EOPNOTSUPP; -} - -static int dsa_port_mdb_dump(struct dsa_port *dp, - struct switchdev_obj_port_mdb *mdb, - switchdev_obj_dump_cb_t *cb) -{ - struct dsa_switch *ds = dp->ds; - - if (ds->ops->port_mdb_dump) - return ds->ops->port_mdb_dump(ds, dp->index, mdb, cb); - - return -EOPNOTSUPP; -} - static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct dsa_slave_priv *p = netdev_priv(dev); -- cgit v1.2.3 From 076e713365c9f4ca1ff3eca9122664a5359b94da Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 19 May 2017 17:00:50 -0400 Subject: net: dsa: move VLAN handlers Move the DSA port code which handles VLAN objects in port.c, where it belongs. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 8 ++++++++ net/dsa/port.c | 41 +++++++++++++++++++++++++++++++++++++++++ net/dsa/slave.c | 41 ----------------------------------------- 3 files changed, 49 insertions(+), 41 deletions(-) (limited to 'net/dsa/port.c') diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index c2a595036746..16021a891095 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -84,6 +84,14 @@ int dsa_port_mdb_del(struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb); int dsa_port_mdb_dump(struct dsa_port *dp, struct switchdev_obj_port_mdb *mdb, switchdev_obj_dump_cb_t *cb); +int dsa_port_vlan_add(struct dsa_port *dp, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans); +int dsa_port_vlan_del(struct dsa_port *dp, + const struct switchdev_obj_port_vlan *vlan); +int dsa_port_vlan_dump(struct dsa_port *dp, + struct switchdev_obj_port_vlan *vlan, + switchdev_obj_dump_cb_t *cb); /* slave.c */ extern const struct dsa_device_ops notag_netdev_ops; diff --git a/net/dsa/port.c b/net/dsa/port.c index 4ed0124a8d4b..f211b0dfb12d 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -247,3 +247,44 @@ int dsa_port_mdb_dump(struct dsa_port *dp, struct switchdev_obj_port_mdb *mdb, return -EOPNOTSUPP; } + +int dsa_port_vlan_add(struct dsa_port *dp, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans) +{ + struct dsa_switch *ds = dp->ds; + + if (switchdev_trans_ph_prepare(trans)) { + if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add) + return -EOPNOTSUPP; + + return ds->ops->port_vlan_prepare(ds, dp->index, vlan, trans); + } + + ds->ops->port_vlan_add(ds, dp->index, vlan, trans); + + return 0; +} + +int dsa_port_vlan_del(struct dsa_port *dp, + const struct switchdev_obj_port_vlan *vlan) +{ + struct dsa_switch *ds = dp->ds; + + if (!ds->ops->port_vlan_del) + return -EOPNOTSUPP; + + return ds->ops->port_vlan_del(ds, dp->index, vlan); +} + +int dsa_port_vlan_dump(struct dsa_port *dp, + struct switchdev_obj_port_vlan *vlan, + switchdev_obj_dump_cb_t *cb) +{ + struct dsa_switch *ds = dp->ds; + + if (ds->ops->port_vlan_dump) + return ds->ops->port_vlan_dump(ds, dp->index, vlan, cb); + + return -EOPNOTSUPP; +} diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 9adcb8267d9a..887e26695519 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -204,47 +204,6 @@ out: return 0; } -static int dsa_port_vlan_add(struct dsa_port *dp, - const struct switchdev_obj_port_vlan *vlan, - struct switchdev_trans *trans) -{ - struct dsa_switch *ds = dp->ds; - - if (switchdev_trans_ph_prepare(trans)) { - if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add) - return -EOPNOTSUPP; - - return ds->ops->port_vlan_prepare(ds, dp->index, vlan, trans); - } - - ds->ops->port_vlan_add(ds, dp->index, vlan, trans); - - return 0; -} - -static int dsa_port_vlan_del(struct dsa_port *dp, - const struct switchdev_obj_port_vlan *vlan) -{ - struct dsa_switch *ds = dp->ds; - - if (!ds->ops->port_vlan_del) - return -EOPNOTSUPP; - - return ds->ops->port_vlan_del(ds, dp->index, vlan); -} - -static int dsa_port_vlan_dump(struct dsa_port *dp, - struct switchdev_obj_port_vlan *vlan, - switchdev_obj_dump_cb_t *cb) -{ - struct dsa_switch *ds = dp->ds; - - if (ds->ops->port_vlan_dump) - return ds->ops->port_vlan_dump(ds, dp->index, vlan, cb); - - return -EOPNOTSUPP; -} - static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct dsa_slave_priv *p = netdev_priv(dev); -- cgit v1.2.3 From 1faabf7440f17999f41973e91878c13ad9f080b2 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 19 May 2017 17:00:52 -0400 Subject: net: dsa: add notifier for ageing time This patch keeps the port-wide ageing time handling code in dsa_port_ageing_time, pushes the requested ageing time value in a new switch fabric notification, and moves the switch-wide ageing time handling code in dsa_switch_ageing_time. This has the effect that now not only the switch that the target port belongs to can be programmed, but all switches composing the switch fabric. For the moment, keep the current behavior and ignore other switches. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 8 ++++++++ net/dsa/port.c | 37 ++++++++----------------------------- net/dsa/switch.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 29 deletions(-) (limited to 'net/dsa/port.c') diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index c19241eb094b..becaf8a61b13 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -17,10 +17,18 @@ #include enum { + DSA_NOTIFIER_AGEING_TIME, DSA_NOTIFIER_BRIDGE_JOIN, DSA_NOTIFIER_BRIDGE_LEAVE, }; +/* DSA_NOTIFIER_AGEING_TIME */ +struct dsa_notifier_ageing_time_info { + struct switchdev_trans *trans; + unsigned int ageing_time; + int sw_index; +}; + /* DSA_NOTIFIER_BRIDGE_* */ struct dsa_notifier_bridge_info { struct net_device *br; diff --git a/net/dsa/port.c b/net/dsa/port.c index f211b0dfb12d..59328a35394d 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -128,44 +128,23 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, return 0; } -static unsigned int dsa_fastest_ageing_time(struct dsa_switch *ds, - unsigned int ageing_time) -{ - int i; - - for (i = 0; i < ds->num_ports; ++i) { - struct dsa_port *dp = &ds->ports[i]; - - if (dp->ageing_time && dp->ageing_time < ageing_time) - ageing_time = dp->ageing_time; - } - - return ageing_time; -} - int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, struct switchdev_trans *trans) { unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock); unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies); - struct dsa_switch *ds = dp->ds; + struct dsa_notifier_ageing_time_info info = { + .ageing_time = ageing_time, + .sw_index = dp->ds->index, + .trans = 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; - } + if (switchdev_trans_ph_prepare(trans)) + return dsa_port_notify(dp, DSA_NOTIFIER_AGEING_TIME, &info); - /* Keep the fastest ageing time in case of multiple bridges */ dp->ageing_time = ageing_time; - ageing_time = dsa_fastest_ageing_time(ds, ageing_time); - if (ds->ops->set_ageing_time) - return ds->ops->set_ageing_time(ds, ageing_time); - - return 0; + return dsa_port_notify(dp, DSA_NOTIFIER_AGEING_TIME, &info); } int dsa_port_fdb_add(struct dsa_port *dp, diff --git a/net/dsa/switch.c b/net/dsa/switch.c index f477053308d2..540770ecc8b0 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -12,9 +12,52 @@ #include #include +#include #include "dsa_priv.h" +static unsigned int dsa_switch_fastest_ageing_time(struct dsa_switch *ds, + unsigned int ageing_time) +{ + int i; + + for (i = 0; i < ds->num_ports; ++i) { + struct dsa_port *dp = &ds->ports[i]; + + if (dp->ageing_time && dp->ageing_time < ageing_time) + ageing_time = dp->ageing_time; + } + + return ageing_time; +} + +static int dsa_switch_ageing_time(struct dsa_switch *ds, + struct dsa_notifier_ageing_time_info *info) +{ + unsigned int ageing_time = info->ageing_time; + struct switchdev_trans *trans = info->trans; + + /* Do not care yet about other switch chips of the fabric */ + if (ds->index != info->sw_index) + return 0; + + 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; + } + + /* Program the fastest ageing time in case of multiple bridges */ + ageing_time = dsa_switch_fastest_ageing_time(ds, ageing_time); + + if (ds->ops->set_ageing_time) + return ds->ops->set_ageing_time(ds, ageing_time); + + return 0; +} + static int dsa_switch_bridge_join(struct dsa_switch *ds, struct dsa_notifier_bridge_info *info) { @@ -48,6 +91,9 @@ static int dsa_switch_event(struct notifier_block *nb, int err; switch (event) { + case DSA_NOTIFIER_AGEING_TIME: + err = dsa_switch_ageing_time(ds, info); + break; case DSA_NOTIFIER_BRIDGE_JOIN: err = dsa_switch_bridge_join(ds, info); break; -- cgit v1.2.3 From 685fb6a40ddace10a0bc8a680ab6ba65c6cdfdaf Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 19 May 2017 17:00:53 -0400 Subject: net: dsa: add FDB notifier Add two new DSA_NOTIFIER_FDB_ADD and DSA_NOTIFIER_FDB_DEL events to notify not only a single switch, but all switches of a the fabric when an FDB entry is added or removed. For the moment, keep the current behavior and ignore other switches. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 10 ++++++++++ net/dsa/port.c | 29 +++++++++++++---------------- net/dsa/switch.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 16 deletions(-) (limited to 'net/dsa/port.c') diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index becaf8a61b13..6a7d0d7d0489 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -20,6 +20,8 @@ enum { DSA_NOTIFIER_AGEING_TIME, DSA_NOTIFIER_BRIDGE_JOIN, DSA_NOTIFIER_BRIDGE_LEAVE, + DSA_NOTIFIER_FDB_ADD, + DSA_NOTIFIER_FDB_DEL, }; /* DSA_NOTIFIER_AGEING_TIME */ @@ -36,6 +38,14 @@ struct dsa_notifier_bridge_info { int port; }; +/* DSA_NOTIFIER_FDB_* */ +struct dsa_notifier_fdb_info { + const struct switchdev_obj_port_fdb *fdb; + struct switchdev_trans *trans; + int sw_index; + int port; +}; + struct dsa_device_ops { struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev, diff --git a/net/dsa/port.c b/net/dsa/port.c index 59328a35394d..ed88d8381642 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -151,29 +151,26 @@ int dsa_port_fdb_add(struct dsa_port *dp, const struct switchdev_obj_port_fdb *fdb, struct switchdev_trans *trans) { - struct dsa_switch *ds = dp->ds; - - if (switchdev_trans_ph_prepare(trans)) { - if (!ds->ops->port_fdb_prepare || !ds->ops->port_fdb_add) - return -EOPNOTSUPP; - - return ds->ops->port_fdb_prepare(ds, dp->index, fdb, trans); - } - - ds->ops->port_fdb_add(ds, dp->index, fdb, trans); + struct dsa_notifier_fdb_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .trans = trans, + .fdb = fdb, + }; - return 0; + return dsa_port_notify(dp, DSA_NOTIFIER_FDB_ADD, &info); } int dsa_port_fdb_del(struct dsa_port *dp, const struct switchdev_obj_port_fdb *fdb) { - struct dsa_switch *ds = dp->ds; - - if (ds->ops->port_fdb_del) - return -EOPNOTSUPP; + struct dsa_notifier_fdb_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .fdb = fdb, + }; - return ds->ops->port_fdb_del(ds, dp->index, fdb); + return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info); } int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb, diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 540770ecc8b0..e71cc860d32c 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -84,6 +84,43 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, return 0; } +static int dsa_switch_fdb_add(struct dsa_switch *ds, + struct dsa_notifier_fdb_info *info) +{ + const struct switchdev_obj_port_fdb *fdb = info->fdb; + struct switchdev_trans *trans = info->trans; + + /* Do not care yet about other switch chips of the fabric */ + if (ds->index != info->sw_index) + return 0; + + if (switchdev_trans_ph_prepare(trans)) { + if (!ds->ops->port_fdb_prepare || !ds->ops->port_fdb_add) + return -EOPNOTSUPP; + + return ds->ops->port_fdb_prepare(ds, info->port, fdb, trans); + } + + ds->ops->port_fdb_add(ds, info->port, fdb, trans); + + return 0; +} + +static int dsa_switch_fdb_del(struct dsa_switch *ds, + struct dsa_notifier_fdb_info *info) +{ + const struct switchdev_obj_port_fdb *fdb = info->fdb; + + /* Do not care yet about other switch chips of the fabric */ + if (ds->index != info->sw_index) + return 0; + + if (!ds->ops->port_fdb_del) + return -EOPNOTSUPP; + + return ds->ops->port_fdb_del(ds, info->port, fdb); +} + static int dsa_switch_event(struct notifier_block *nb, unsigned long event, void *info) { @@ -100,6 +137,12 @@ static int dsa_switch_event(struct notifier_block *nb, case DSA_NOTIFIER_BRIDGE_LEAVE: err = dsa_switch_bridge_leave(ds, info); break; + case DSA_NOTIFIER_FDB_ADD: + err = dsa_switch_fdb_add(ds, info); + break; + case DSA_NOTIFIER_FDB_DEL: + err = dsa_switch_fdb_del(ds, info); + break; default: err = -EOPNOTSUPP; break; -- cgit v1.2.3 From 8ae5bcdc5d98a99e59f194101e7acd2e9d055758 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 19 May 2017 17:00:54 -0400 Subject: net: dsa: add MDB notifier Add two new DSA_NOTIFIER_MDB_ADD and DSA_NOTIFIER_MDB_DEL events to notify not only a single switch, but all switches of a the fabric when an MDB entry is added or removed. For the moment, keep the current behavior and ignore other switches. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 10 ++++++++++ net/dsa/port.c | 29 +++++++++++++---------------- net/dsa/switch.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 16 deletions(-) (limited to 'net/dsa/port.c') diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 6a7d0d7d0489..2b60293b325c 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -22,6 +22,8 @@ enum { DSA_NOTIFIER_BRIDGE_LEAVE, DSA_NOTIFIER_FDB_ADD, DSA_NOTIFIER_FDB_DEL, + DSA_NOTIFIER_MDB_ADD, + DSA_NOTIFIER_MDB_DEL, }; /* DSA_NOTIFIER_AGEING_TIME */ @@ -46,6 +48,14 @@ struct dsa_notifier_fdb_info { int port; }; +/* DSA_NOTIFIER_MDB_* */ +struct dsa_notifier_mdb_info { + const struct switchdev_obj_port_mdb *mdb; + struct switchdev_trans *trans; + int sw_index; + int port; +}; + struct dsa_device_ops { struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev, diff --git a/net/dsa/port.c b/net/dsa/port.c index ed88d8381642..c7c4920e7bc9 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -188,29 +188,26 @@ int dsa_port_mdb_add(struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb, struct switchdev_trans *trans) { - struct dsa_switch *ds = dp->ds; - - if (switchdev_trans_ph_prepare(trans)) { - if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add) - return -EOPNOTSUPP; - - return ds->ops->port_mdb_prepare(ds, dp->index, mdb, trans); - } - - ds->ops->port_mdb_add(ds, dp->index, mdb, trans); + struct dsa_notifier_mdb_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .trans = trans, + .mdb = mdb, + }; - return 0; + return dsa_port_notify(dp, DSA_NOTIFIER_MDB_ADD, &info); } int dsa_port_mdb_del(struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb) { - struct dsa_switch *ds = dp->ds; - - if (ds->ops->port_mdb_del) - return ds->ops->port_mdb_del(ds, dp->index, mdb); + struct dsa_notifier_mdb_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .mdb = mdb, + }; - return -EOPNOTSUPP; + return dsa_port_notify(dp, DSA_NOTIFIER_MDB_DEL, &info); } int dsa_port_mdb_dump(struct dsa_port *dp, struct switchdev_obj_port_mdb *mdb, diff --git a/net/dsa/switch.c b/net/dsa/switch.c index e71cc860d32c..b7e8e45869fc 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -121,6 +121,43 @@ static int dsa_switch_fdb_del(struct dsa_switch *ds, return ds->ops->port_fdb_del(ds, info->port, fdb); } +static int dsa_switch_mdb_add(struct dsa_switch *ds, + struct dsa_notifier_mdb_info *info) +{ + const struct switchdev_obj_port_mdb *mdb = info->mdb; + struct switchdev_trans *trans = info->trans; + + /* Do not care yet about other switch chips of the fabric */ + if (ds->index != info->sw_index) + return 0; + + if (switchdev_trans_ph_prepare(trans)) { + if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add) + return -EOPNOTSUPP; + + return ds->ops->port_mdb_prepare(ds, info->port, mdb, trans); + } + + ds->ops->port_mdb_add(ds, info->port, mdb, trans); + + return 0; +} + +static int dsa_switch_mdb_del(struct dsa_switch *ds, + struct dsa_notifier_mdb_info *info) +{ + const struct switchdev_obj_port_mdb *mdb = info->mdb; + + /* Do not care yet about other switch chips of the fabric */ + if (ds->index != info->sw_index) + return 0; + + if (!ds->ops->port_mdb_del) + return -EOPNOTSUPP; + + return ds->ops->port_mdb_del(ds, info->port, mdb); +} + static int dsa_switch_event(struct notifier_block *nb, unsigned long event, void *info) { @@ -143,6 +180,12 @@ static int dsa_switch_event(struct notifier_block *nb, case DSA_NOTIFIER_FDB_DEL: err = dsa_switch_fdb_del(ds, info); break; + case DSA_NOTIFIER_MDB_ADD: + err = dsa_switch_mdb_add(ds, info); + break; + case DSA_NOTIFIER_MDB_DEL: + err = dsa_switch_mdb_del(ds, info); + break; default: err = -EOPNOTSUPP; break; -- cgit v1.2.3 From d0c627b8740ca6243054263fbc98981a36ac5618 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 19 May 2017 17:00:55 -0400 Subject: net: dsa: add VLAN notifier Add two new DSA_NOTIFIER_VLAN_ADD and DSA_NOTIFIER_VLAN_DEL events to notify not only a single switch, but all switches of a the fabric when an VLAN entry is added or removed. For the moment, keep the current behavior and ignore other switches. Signed-off-by: Vivien Didelot Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 10 ++++++++++ net/dsa/port.c | 29 +++++++++++++---------------- net/dsa/switch.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 16 deletions(-) (limited to 'net/dsa/port.c') diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 2b60293b325c..1d52f9051d0e 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -24,6 +24,8 @@ enum { DSA_NOTIFIER_FDB_DEL, DSA_NOTIFIER_MDB_ADD, DSA_NOTIFIER_MDB_DEL, + DSA_NOTIFIER_VLAN_ADD, + DSA_NOTIFIER_VLAN_DEL, }; /* DSA_NOTIFIER_AGEING_TIME */ @@ -56,6 +58,14 @@ struct dsa_notifier_mdb_info { int port; }; +/* DSA_NOTIFIER_VLAN_* */ +struct dsa_notifier_vlan_info { + const struct switchdev_obj_port_vlan *vlan; + struct switchdev_trans *trans; + int sw_index; + int port; +}; + struct dsa_device_ops { struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev, diff --git a/net/dsa/port.c b/net/dsa/port.c index c7c4920e7bc9..c88c0cec8454 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -225,29 +225,26 @@ int dsa_port_vlan_add(struct dsa_port *dp, const struct switchdev_obj_port_vlan *vlan, struct switchdev_trans *trans) { - struct dsa_switch *ds = dp->ds; - - if (switchdev_trans_ph_prepare(trans)) { - if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add) - return -EOPNOTSUPP; - - return ds->ops->port_vlan_prepare(ds, dp->index, vlan, trans); - } - - ds->ops->port_vlan_add(ds, dp->index, vlan, trans); + struct dsa_notifier_vlan_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .trans = trans, + .vlan = vlan, + }; - return 0; + return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info); } int dsa_port_vlan_del(struct dsa_port *dp, const struct switchdev_obj_port_vlan *vlan) { - struct dsa_switch *ds = dp->ds; - - if (!ds->ops->port_vlan_del) - return -EOPNOTSUPP; + struct dsa_notifier_vlan_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .vlan = vlan, + }; - return ds->ops->port_vlan_del(ds, dp->index, vlan); + return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info); } int dsa_port_vlan_dump(struct dsa_port *dp, diff --git a/net/dsa/switch.c b/net/dsa/switch.c index b7e8e45869fc..c1e4b2d5a3ae 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -158,6 +158,43 @@ static int dsa_switch_mdb_del(struct dsa_switch *ds, return ds->ops->port_mdb_del(ds, info->port, mdb); } +static int dsa_switch_vlan_add(struct dsa_switch *ds, + struct dsa_notifier_vlan_info *info) +{ + const struct switchdev_obj_port_vlan *vlan = info->vlan; + struct switchdev_trans *trans = info->trans; + + /* Do not care yet about other switch chips of the fabric */ + if (ds->index != info->sw_index) + return 0; + + if (switchdev_trans_ph_prepare(trans)) { + if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add) + return -EOPNOTSUPP; + + return ds->ops->port_vlan_prepare(ds, info->port, vlan, trans); + } + + ds->ops->port_vlan_add(ds, info->port, vlan, trans); + + return 0; +} + +static int dsa_switch_vlan_del(struct dsa_switch *ds, + struct dsa_notifier_vlan_info *info) +{ + const struct switchdev_obj_port_vlan *vlan = info->vlan; + + /* Do not care yet about other switch chips of the fabric */ + if (ds->index != info->sw_index) + return 0; + + if (!ds->ops->port_vlan_del) + return -EOPNOTSUPP; + + return ds->ops->port_vlan_del(ds, info->port, vlan); +} + static int dsa_switch_event(struct notifier_block *nb, unsigned long event, void *info) { @@ -186,6 +223,12 @@ static int dsa_switch_event(struct notifier_block *nb, case DSA_NOTIFIER_MDB_DEL: err = dsa_switch_mdb_del(ds, info); break; + case DSA_NOTIFIER_VLAN_ADD: + err = dsa_switch_vlan_add(ds, info); + break; + case DSA_NOTIFIER_VLAN_DEL: + err = dsa_switch_vlan_del(ds, info); + break; default: err = -EOPNOTSUPP; break; -- cgit v1.2.3 From 64dba236a15770af1e07f90f23a54789c9f9a3ba Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Tue, 23 May 2017 15:20:59 -0400 Subject: net: dsa: support cross-chip ageing time Now that the switchdev bridge ageing time attribute is propagated to all switch chips of the fabric, each switch can check if the requested value is valid and program itself, so that the whole fabric shares a common ageing time setting. This is especially needed for switch chips in between others, containing no bridge port members but evidently used in the data path. To achieve that, remove the condition which skips the other switches. We also don't need to identify the target switch anymore, thus remove the sw_index member of the dsa_notifier_ageing_time_info notifier structure. On ZII Dev Rev B (with two 88E6352 and one 88E6185) and ZII Dev Rev C (with two 88E6390X), we have the following hardware configuration: # ip link add name br0 type bridge # ip link set master br0 dev lan6 br0: port 1(lan6) entered blocking state br0: port 1(lan6) entered disabled state # echo 2000 > /sys/class/net/br0/bridge/ageing_time Before this patch: zii-rev-b# cat /sys/kernel/debug/mv88e6xxx/sw*/age_time 300000 300000 15000 zii-rev-c# cat /sys/kernel/debug/mv88e6xxx/sw*/age_time 300000 18750 After this patch: zii-rev-b# cat /sys/kernel/debug/mv88e6xxx/sw*/age_time 15000 15000 15000 zii-rev-c# cat /sys/kernel/debug/mv88e6xxx/sw*/age_time 18750 18750 Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 1 - net/dsa/port.c | 1 - net/dsa/switch.c | 4 ---- 3 files changed, 6 deletions(-) (limited to 'net/dsa/port.c') diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 1d52f9051d0e..c1d4180651af 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -32,7 +32,6 @@ enum { struct dsa_notifier_ageing_time_info { struct switchdev_trans *trans; unsigned int ageing_time; - int sw_index; }; /* DSA_NOTIFIER_BRIDGE_* */ diff --git a/net/dsa/port.c b/net/dsa/port.c index c88c0cec8454..efc3bce3a89d 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -135,7 +135,6 @@ int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies); struct dsa_notifier_ageing_time_info info = { .ageing_time = ageing_time, - .sw_index = dp->ds->index, .trans = trans, }; diff --git a/net/dsa/switch.c b/net/dsa/switch.c index c1e4b2d5a3ae..d8e5c311ee7c 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -37,10 +37,6 @@ static int dsa_switch_ageing_time(struct dsa_switch *ds, unsigned int ageing_time = info->ageing_time; struct switchdev_trans *trans = info->trans; - /* Do not care yet about other switch chips of the fabric */ - if (ds->index != info->sw_index) - return 0; - if (switchdev_trans_ph_prepare(trans)) { if (ds->ageing_time_min && ageing_time < ds->ageing_time_min) return -ERANGE; -- cgit v1.2.3