net: dsa: convert cross-chip notifiers to iterate using dp

The majority of cross-chip switch notifiers need to filter in some way
over the type of ports: some install VLANs etc on all cascade ports.

The difference is that the matching function, which filters by port
type, is separate from the function where the iteration happens. So this
patch needs to refactor the matching functions' prototypes as well, to
take the dp as argument.

In a future patch/series, I might convert dsa_towards_port to return a
struct dsa_port *dp too, but at the moment it is a bit entangled with
dsa_routing_port which is also used by mv88e6xxx and they both return an
int port. So keep dsa_towards_port the way it is and convert it into a
dp using dsa_to_port.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Vladimir Oltean 2021-10-20 20:49:53 +03:00 committed by David S. Miller
parent 57d77986e7
commit fac6abd5f1
2 changed files with 112 additions and 102 deletions

View file

@ -46,10 +46,10 @@ static int dsa_switch_ageing_time(struct dsa_switch *ds,
return 0;
}
static bool dsa_switch_mtu_match(struct dsa_switch *ds, int port,
static bool dsa_port_mtu_match(struct dsa_port *dp,
struct dsa_notifier_mtu_info *info)
{
if (ds->index == info->sw_index && port == info->port)
if (dp->ds->index == info->sw_index && dp->index == info->port)
return true;
/* Do not propagate to other switches in the tree if the notifier was
@ -58,7 +58,7 @@ static bool dsa_switch_mtu_match(struct dsa_switch *ds, int port,
if (info->targeted_match)
return false;
if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
if (dsa_port_is_dsa(dp) || dsa_port_is_cpu(dp))
return true;
return false;
@ -67,14 +67,16 @@ static bool dsa_switch_mtu_match(struct dsa_switch *ds, int port,
static int dsa_switch_mtu(struct dsa_switch *ds,
struct dsa_notifier_mtu_info *info)
{
int port, ret;
struct dsa_port *dp;
int ret;
if (!ds->ops->port_change_mtu)
return -EOPNOTSUPP;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_mtu_match(ds, port, info)) {
ret = ds->ops->port_change_mtu(ds, port, info->mtu);
dsa_switch_for_each_port(dp, ds) {
if (dsa_port_mtu_match(dp, info)) {
ret = ds->ops->port_change_mtu(ds, dp->index,
info->mtu);
if (ret)
return ret;
}
@ -177,18 +179,18 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds,
* DSA links) that sit between the targeted port on which the notifier was
* emitted and its dedicated CPU port.
*/
static bool dsa_switch_host_address_match(struct dsa_switch *ds, int port,
static bool dsa_port_host_address_match(struct dsa_port *dp,
int info_sw_index, int info_port)
{
struct dsa_port *targeted_dp, *cpu_dp;
struct dsa_switch *targeted_ds;
targeted_ds = dsa_switch_find(ds->dst->index, info_sw_index);
targeted_ds = dsa_switch_find(dp->ds->dst->index, info_sw_index);
targeted_dp = dsa_to_port(targeted_ds, info_port);
cpu_dp = targeted_dp->cpu_dp;
if (dsa_switch_is_upstream_of(ds, targeted_ds))
return port == dsa_towards_port(ds, cpu_dp->ds->index,
if (dsa_switch_is_upstream_of(dp->ds, targeted_ds))
return dp->index == dsa_towards_port(dp->ds, cpu_dp->ds->index,
cpu_dp->index);
return false;
@ -207,11 +209,12 @@ static struct dsa_mac_addr *dsa_mac_addr_find(struct list_head *addr_list,
return NULL;
}
static int dsa_switch_do_mdb_add(struct dsa_switch *ds, int port,
static int dsa_port_do_mdb_add(struct dsa_port *dp,
const struct switchdev_obj_port_mdb *mdb)
{
struct dsa_port *dp = dsa_to_port(ds, port);
struct dsa_switch *ds = dp->ds;
struct dsa_mac_addr *a;
int port = dp->index;
int err;
/* No need to bother with refcounting for user ports */
@ -242,11 +245,12 @@ static int dsa_switch_do_mdb_add(struct dsa_switch *ds, int port,
return 0;
}
static int dsa_switch_do_mdb_del(struct dsa_switch *ds, int port,
static int dsa_port_do_mdb_del(struct dsa_port *dp,
const struct switchdev_obj_port_mdb *mdb)
{
struct dsa_port *dp = dsa_to_port(ds, port);
struct dsa_switch *ds = dp->ds;
struct dsa_mac_addr *a;
int port = dp->index;
int err;
/* No need to bother with refcounting for user ports */
@ -272,11 +276,12 @@ static int dsa_switch_do_mdb_del(struct dsa_switch *ds, int port,
return 0;
}
static int dsa_switch_do_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr,
u16 vid)
{
struct dsa_port *dp = dsa_to_port(ds, port);
struct dsa_switch *ds = dp->ds;
struct dsa_mac_addr *a;
int port = dp->index;
int err;
/* No need to bother with refcounting for user ports */
@ -307,11 +312,12 @@ static int dsa_switch_do_fdb_add(struct dsa_switch *ds, int port,
return 0;
}
static int dsa_switch_do_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr,
u16 vid)
{
struct dsa_port *dp = dsa_to_port(ds, port);
struct dsa_switch *ds = dp->ds;
struct dsa_mac_addr *a;
int port = dp->index;
int err;
/* No need to bother with refcounting for user ports */
@ -340,17 +346,16 @@ static int dsa_switch_do_fdb_del(struct dsa_switch *ds, int port,
static int dsa_switch_host_fdb_add(struct dsa_switch *ds,
struct dsa_notifier_fdb_info *info)
{
struct dsa_port *dp;
int err = 0;
int port;
if (!ds->ops->port_fdb_add)
return -EOPNOTSUPP;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_host_address_match(ds, port, info->sw_index,
dsa_switch_for_each_port(dp, ds) {
if (dsa_port_host_address_match(dp, info->sw_index,
info->port)) {
err = dsa_switch_do_fdb_add(ds, port, info->addr,
info->vid);
err = dsa_port_do_fdb_add(dp, info->addr, info->vid);
if (err)
break;
}
@ -362,17 +367,16 @@ static int dsa_switch_host_fdb_add(struct dsa_switch *ds,
static int dsa_switch_host_fdb_del(struct dsa_switch *ds,
struct dsa_notifier_fdb_info *info)
{
struct dsa_port *dp;
int err = 0;
int port;
if (!ds->ops->port_fdb_del)
return -EOPNOTSUPP;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_host_address_match(ds, port, info->sw_index,
dsa_switch_for_each_port(dp, ds) {
if (dsa_port_host_address_match(dp, info->sw_index,
info->port)) {
err = dsa_switch_do_fdb_del(ds, port, info->addr,
info->vid);
err = dsa_port_do_fdb_del(dp, info->addr, info->vid);
if (err)
break;
}
@ -385,22 +389,24 @@ static int dsa_switch_fdb_add(struct dsa_switch *ds,
struct dsa_notifier_fdb_info *info)
{
int port = dsa_towards_port(ds, info->sw_index, info->port);
struct dsa_port *dp = dsa_to_port(ds, port);
if (!ds->ops->port_fdb_add)
return -EOPNOTSUPP;
return dsa_switch_do_fdb_add(ds, port, info->addr, info->vid);
return dsa_port_do_fdb_add(dp, info->addr, info->vid);
}
static int dsa_switch_fdb_del(struct dsa_switch *ds,
struct dsa_notifier_fdb_info *info)
{
int port = dsa_towards_port(ds, info->sw_index, info->port);
struct dsa_port *dp = dsa_to_port(ds, port);
if (!ds->ops->port_fdb_del)
return -EOPNOTSUPP;
return dsa_switch_do_fdb_del(ds, port, info->addr, info->vid);
return dsa_port_do_fdb_del(dp, info->addr, info->vid);
}
static int dsa_switch_hsr_join(struct dsa_switch *ds,
@ -466,37 +472,39 @@ static int dsa_switch_mdb_add(struct dsa_switch *ds,
struct dsa_notifier_mdb_info *info)
{
int port = dsa_towards_port(ds, info->sw_index, info->port);
struct dsa_port *dp = dsa_to_port(ds, port);
if (!ds->ops->port_mdb_add)
return -EOPNOTSUPP;
return dsa_switch_do_mdb_add(ds, port, info->mdb);
return dsa_port_do_mdb_add(dp, info->mdb);
}
static int dsa_switch_mdb_del(struct dsa_switch *ds,
struct dsa_notifier_mdb_info *info)
{
int port = dsa_towards_port(ds, info->sw_index, info->port);
struct dsa_port *dp = dsa_to_port(ds, port);
if (!ds->ops->port_mdb_del)
return -EOPNOTSUPP;
return dsa_switch_do_mdb_del(ds, port, info->mdb);
return dsa_port_do_mdb_del(dp, info->mdb);
}
static int dsa_switch_host_mdb_add(struct dsa_switch *ds,
struct dsa_notifier_mdb_info *info)
{
struct dsa_port *dp;
int err = 0;
int port;
if (!ds->ops->port_mdb_add)
return -EOPNOTSUPP;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_host_address_match(ds, port, info->sw_index,
dsa_switch_for_each_port(dp, ds) {
if (dsa_port_host_address_match(dp, info->sw_index,
info->port)) {
err = dsa_switch_do_mdb_add(ds, port, info->mdb);
err = dsa_port_do_mdb_add(dp, info->mdb);
if (err)
break;
}
@ -508,16 +516,16 @@ static int dsa_switch_host_mdb_add(struct dsa_switch *ds,
static int dsa_switch_host_mdb_del(struct dsa_switch *ds,
struct dsa_notifier_mdb_info *info)
{
struct dsa_port *dp;
int err = 0;
int port;
if (!ds->ops->port_mdb_del)
return -EOPNOTSUPP;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_host_address_match(ds, port, info->sw_index,
dsa_switch_for_each_port(dp, ds) {
if (dsa_port_host_address_match(dp, info->sw_index,
info->port)) {
err = dsa_switch_do_mdb_del(ds, port, info->mdb);
err = dsa_port_do_mdb_del(dp, info->mdb);
if (err)
break;
}
@ -526,13 +534,13 @@ static int dsa_switch_host_mdb_del(struct dsa_switch *ds,
return err;
}
static bool dsa_switch_vlan_match(struct dsa_switch *ds, int port,
static bool dsa_port_vlan_match(struct dsa_port *dp,
struct dsa_notifier_vlan_info *info)
{
if (ds->index == info->sw_index && port == info->port)
if (dp->ds->index == info->sw_index && dp->index == info->port)
return true;
if (dsa_is_dsa_port(ds, port))
if (dsa_port_is_dsa(dp))
return true;
return false;
@ -541,14 +549,15 @@ static bool dsa_switch_vlan_match(struct dsa_switch *ds, int port,
static int dsa_switch_vlan_add(struct dsa_switch *ds,
struct dsa_notifier_vlan_info *info)
{
int port, err;
struct dsa_port *dp;
int err;
if (!ds->ops->port_vlan_add)
return -EOPNOTSUPP;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_vlan_match(ds, port, info)) {
err = ds->ops->port_vlan_add(ds, port, info->vlan,
dsa_switch_for_each_port(dp, ds) {
if (dsa_port_vlan_match(dp, info)) {
err = ds->ops->port_vlan_add(ds, dp->index, info->vlan,
info->extack);
if (err)
return err;

View file

@ -138,12 +138,13 @@ dsa_tag_8021q_vlan_find(struct dsa_8021q_context *ctx, int port, u16 vid)
return NULL;
}
static int dsa_switch_do_tag_8021q_vlan_add(struct dsa_switch *ds, int port,
u16 vid, u16 flags)
static int dsa_port_do_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid,
u16 flags)
{
struct dsa_8021q_context *ctx = ds->tag_8021q_ctx;
struct dsa_port *dp = dsa_to_port(ds, port);
struct dsa_8021q_context *ctx = dp->ds->tag_8021q_ctx;
struct dsa_switch *ds = dp->ds;
struct dsa_tag_8021q_vlan *v;
int port = dp->index;
int err;
/* No need to bother with refcounting for user ports */
@ -174,12 +175,12 @@ static int dsa_switch_do_tag_8021q_vlan_add(struct dsa_switch *ds, int port,
return 0;
}
static int dsa_switch_do_tag_8021q_vlan_del(struct dsa_switch *ds, int port,
u16 vid)
static int dsa_port_do_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid)
{
struct dsa_8021q_context *ctx = ds->tag_8021q_ctx;
struct dsa_port *dp = dsa_to_port(ds, port);
struct dsa_8021q_context *ctx = dp->ds->tag_8021q_ctx;
struct dsa_switch *ds = dp->ds;
struct dsa_tag_8021q_vlan *v;
int port = dp->index;
int err;
/* No need to bother with refcounting for user ports */
@ -206,14 +207,16 @@ static int dsa_switch_do_tag_8021q_vlan_del(struct dsa_switch *ds, int port,
}
static bool
dsa_switch_tag_8021q_vlan_match(struct dsa_switch *ds, int port,
dsa_port_tag_8021q_vlan_match(struct dsa_port *dp,
struct dsa_notifier_tag_8021q_vlan_info *info)
{
if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
struct dsa_switch *ds = dp->ds;
if (dsa_port_is_dsa(dp) || dsa_port_is_cpu(dp))
return true;
if (ds->dst->index == info->tree_index && ds->index == info->sw_index)
return port == info->port;
return dp->index == info->port;
return false;
}
@ -221,7 +224,8 @@ dsa_switch_tag_8021q_vlan_match(struct dsa_switch *ds, int port,
int dsa_switch_tag_8021q_vlan_add(struct dsa_switch *ds,
struct dsa_notifier_tag_8021q_vlan_info *info)
{
int port, err;
struct dsa_port *dp;
int err;
/* Since we use dsa_broadcast(), there might be other switches in other
* trees which don't support tag_8021q, so don't return an error.
@ -231,20 +235,19 @@ int dsa_switch_tag_8021q_vlan_add(struct dsa_switch *ds,
if (!ds->ops->tag_8021q_vlan_add || !ds->tag_8021q_ctx)
return 0;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_tag_8021q_vlan_match(ds, port, info)) {
dsa_switch_for_each_port(dp, ds) {
if (dsa_port_tag_8021q_vlan_match(dp, info)) {
u16 flags = 0;
if (dsa_is_user_port(ds, port))
if (dsa_port_is_user(dp))
flags |= BRIDGE_VLAN_INFO_UNTAGGED;
if (vid_is_dsa_8021q_rxvlan(info->vid) &&
dsa_8021q_rx_switch_id(info->vid) == ds->index &&
dsa_8021q_rx_source_port(info->vid) == port)
dsa_8021q_rx_source_port(info->vid) == dp->index)
flags |= BRIDGE_VLAN_INFO_PVID;
err = dsa_switch_do_tag_8021q_vlan_add(ds, port,
info->vid,
err = dsa_port_do_tag_8021q_vlan_add(dp, info->vid,
flags);
if (err)
return err;
@ -257,15 +260,15 @@ int dsa_switch_tag_8021q_vlan_add(struct dsa_switch *ds,
int dsa_switch_tag_8021q_vlan_del(struct dsa_switch *ds,
struct dsa_notifier_tag_8021q_vlan_info *info)
{
int port, err;
struct dsa_port *dp;
int err;
if (!ds->ops->tag_8021q_vlan_del || !ds->tag_8021q_ctx)
return 0;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_tag_8021q_vlan_match(ds, port, info)) {
err = dsa_switch_do_tag_8021q_vlan_del(ds, port,
info->vid);
dsa_switch_for_each_port(dp, ds) {
if (dsa_port_tag_8021q_vlan_match(dp, info)) {
err = dsa_port_do_tag_8021q_vlan_del(dp, info->vid);
if (err)
return err;
}
@ -321,15 +324,14 @@ int dsa_switch_tag_8021q_vlan_del(struct dsa_switch *ds,
* +-+-----+-+-----+-+-----+-+-----+-+ +-+-----+-+-----+-+-----+-+-----+-+
* swp0 swp1 swp2 swp3 swp0 swp1 swp2 swp3
*/
static bool dsa_tag_8021q_bridge_match(struct dsa_switch *ds, int port,
static bool
dsa_port_tag_8021q_bridge_match(struct dsa_port *dp,
struct dsa_notifier_bridge_info *info)
{
struct dsa_port *dp = dsa_to_port(ds, port);
/* Don't match on self */
if (ds->dst->index == info->tree_index &&
ds->index == info->sw_index &&
port == info->port)
if (dp->ds->dst->index == info->tree_index &&
dp->ds->index == info->sw_index &&
dp->index == info->port)
return false;
if (dsa_port_is_user(dp))
@ -343,8 +345,9 @@ int dsa_tag_8021q_bridge_join(struct dsa_switch *ds,
{
struct dsa_switch *targeted_ds;
struct dsa_port *targeted_dp;
struct dsa_port *dp;
u16 targeted_rx_vid;
int err, port;
int err;
if (!ds->tag_8021q_ctx)
return 0;
@ -353,11 +356,10 @@ int dsa_tag_8021q_bridge_join(struct dsa_switch *ds,
targeted_dp = dsa_to_port(targeted_ds, info->port);
targeted_rx_vid = dsa_8021q_rx_vid(targeted_ds, info->port);
for (port = 0; port < ds->num_ports; port++) {
struct dsa_port *dp = dsa_to_port(ds, port);
u16 rx_vid = dsa_8021q_rx_vid(ds, port);
dsa_switch_for_each_port(dp, ds) {
u16 rx_vid = dsa_8021q_rx_vid(ds, dp->index);
if (!dsa_tag_8021q_bridge_match(ds, port, info))
if (!dsa_port_tag_8021q_bridge_match(dp, info))
continue;
/* Install the RX VID of the targeted port in our VLAN table */
@ -379,8 +381,8 @@ int dsa_tag_8021q_bridge_leave(struct dsa_switch *ds,
{
struct dsa_switch *targeted_ds;
struct dsa_port *targeted_dp;
struct dsa_port *dp;
u16 targeted_rx_vid;
int port;
if (!ds->tag_8021q_ctx)
return 0;
@ -389,11 +391,10 @@ int dsa_tag_8021q_bridge_leave(struct dsa_switch *ds,
targeted_dp = dsa_to_port(targeted_ds, info->port);
targeted_rx_vid = dsa_8021q_rx_vid(targeted_ds, info->port);
for (port = 0; port < ds->num_ports; port++) {
struct dsa_port *dp = dsa_to_port(ds, port);
u16 rx_vid = dsa_8021q_rx_vid(ds, port);
dsa_switch_for_each_port(dp, ds) {
u16 rx_vid = dsa_8021q_rx_vid(ds, dp->index);
if (!dsa_tag_8021q_bridge_match(ds, port, info))
if (!dsa_port_tag_8021q_bridge_match(dp, info))
continue;
/* Remove the RX VID of the targeted port from our VLAN table */