switch.c (60dd57c7479418e2bc902143eb46a2fdcfeecbbb) switch.c (d0004a020bb50263de0e3e775c7b7c7a003e0e0c)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Handling of a single switch chip, part of a switch fabric
4 *
5 * Copyright (c) 2017 Savoir-faire Linux Inc.
6 * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
7 */
8
9#include <linux/if_bridge.h>
10#include <linux/netdevice.h>
11#include <linux/notifier.h>
12#include <linux/if_vlan.h>
13#include <net/switchdev.h>
14
15#include "dsa_priv.h"
16
17static unsigned int dsa_switch_fastest_ageing_time(struct dsa_switch *ds,
18 unsigned int ageing_time)
19{
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Handling of a single switch chip, part of a switch fabric
4 *
5 * Copyright (c) 2017 Savoir-faire Linux Inc.
6 * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
7 */
8
9#include <linux/if_bridge.h>
10#include <linux/netdevice.h>
11#include <linux/notifier.h>
12#include <linux/if_vlan.h>
13#include <net/switchdev.h>
14
15#include "dsa_priv.h"
16
17static unsigned int dsa_switch_fastest_ageing_time(struct dsa_switch *ds,
18 unsigned int ageing_time)
19{
20 int i;
20 struct dsa_port *dp;
21
21
22 for (i = 0; i < ds->num_ports; ++i) {
23 struct dsa_port *dp = dsa_to_port(ds, i);
24
22 dsa_switch_for_each_port(dp, ds)
25 if (dp->ageing_time && dp->ageing_time < ageing_time)
26 ageing_time = dp->ageing_time;
23 if (dp->ageing_time && dp->ageing_time < ageing_time)
24 ageing_time = dp->ageing_time;
27 }
28
29 return ageing_time;
30}
31
32static int dsa_switch_ageing_time(struct dsa_switch *ds,
33 struct dsa_notifier_ageing_time_info *info)
34{
35 unsigned int ageing_time = info->ageing_time;

--- 79 unchanged lines hidden (view full) ---

115
116static int dsa_switch_bridge_leave(struct dsa_switch *ds,
117 struct dsa_notifier_bridge_info *info)
118{
119 struct dsa_switch_tree *dst = ds->dst;
120 struct netlink_ext_ack extack = {0};
121 bool change_vlan_filtering = false;
122 bool vlan_filtering;
25
26 return ageing_time;
27}
28
29static int dsa_switch_ageing_time(struct dsa_switch *ds,
30 struct dsa_notifier_ageing_time_info *info)
31{
32 unsigned int ageing_time = info->ageing_time;

--- 79 unchanged lines hidden (view full) ---

112
113static int dsa_switch_bridge_leave(struct dsa_switch *ds,
114 struct dsa_notifier_bridge_info *info)
115{
116 struct dsa_switch_tree *dst = ds->dst;
117 struct netlink_ext_ack extack = {0};
118 bool change_vlan_filtering = false;
119 bool vlan_filtering;
123 int err, port;
120 struct dsa_port *dp;
121 int err;
124
125 if (dst->index == info->tree_index && ds->index == info->sw_index &&
126 ds->ops->port_bridge_leave)
127 ds->ops->port_bridge_leave(ds, info->port, info->br);
128
129 if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
130 ds->ops->crosschip_bridge_leave)
131 ds->ops->crosschip_bridge_leave(ds, info->tree_index,

--- 13 unchanged lines hidden (view full) ---

145 * event for changing vlan_filtering setting upon slave ports leaving
146 * it. That is a good thing, because that lets us handle it and also
147 * handle the case where the switch's vlan_filtering setting is global
148 * (not per port). When that happens, the correct moment to trigger the
149 * vlan_filtering callback is only when the last port leaves the last
150 * VLAN-aware bridge.
151 */
152 if (change_vlan_filtering && ds->vlan_filtering_is_global) {
122
123 if (dst->index == info->tree_index && ds->index == info->sw_index &&
124 ds->ops->port_bridge_leave)
125 ds->ops->port_bridge_leave(ds, info->port, info->br);
126
127 if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
128 ds->ops->crosschip_bridge_leave)
129 ds->ops->crosschip_bridge_leave(ds, info->tree_index,

--- 13 unchanged lines hidden (view full) ---

143 * event for changing vlan_filtering setting upon slave ports leaving
144 * it. That is a good thing, because that lets us handle it and also
145 * handle the case where the switch's vlan_filtering setting is global
146 * (not per port). When that happens, the correct moment to trigger the
147 * vlan_filtering callback is only when the last port leaves the last
148 * VLAN-aware bridge.
149 */
150 if (change_vlan_filtering && ds->vlan_filtering_is_global) {
153 for (port = 0; port < ds->num_ports; port++) {
151 dsa_switch_for_each_port(dp, ds) {
154 struct net_device *bridge_dev;
155
152 struct net_device *bridge_dev;
153
156 bridge_dev = dsa_to_port(ds, port)->bridge_dev;
154 bridge_dev = dp->bridge_dev;
157
158 if (bridge_dev && br_vlan_enabled(bridge_dev)) {
159 change_vlan_filtering = false;
160 break;
161 }
162 }
163 }
164

--- 409 unchanged lines hidden (view full) ---

574 */
575 return 0;
576}
577
578static int dsa_switch_change_tag_proto(struct dsa_switch *ds,
579 struct dsa_notifier_tag_proto_info *info)
580{
581 const struct dsa_device_ops *tag_ops = info->tag_ops;
155
156 if (bridge_dev && br_vlan_enabled(bridge_dev)) {
157 change_vlan_filtering = false;
158 break;
159 }
160 }
161 }
162

--- 409 unchanged lines hidden (view full) ---

572 */
573 return 0;
574}
575
576static int dsa_switch_change_tag_proto(struct dsa_switch *ds,
577 struct dsa_notifier_tag_proto_info *info)
578{
579 const struct dsa_device_ops *tag_ops = info->tag_ops;
582 int port, err;
580 struct dsa_port *dp, *cpu_dp;
581 int err;
583
584 if (!ds->ops->change_tag_protocol)
585 return -EOPNOTSUPP;
586
587 ASSERT_RTNL();
588
582
583 if (!ds->ops->change_tag_protocol)
584 return -EOPNOTSUPP;
585
586 ASSERT_RTNL();
587
589 for (port = 0; port < ds->num_ports; port++) {
590 if (!dsa_is_cpu_port(ds, port))
591 continue;
592
593 err = ds->ops->change_tag_protocol(ds, port, tag_ops->proto);
588 dsa_switch_for_each_cpu_port(cpu_dp, ds) {
589 err = ds->ops->change_tag_protocol(ds, cpu_dp->index,
590 tag_ops->proto);
594 if (err)
595 return err;
596
591 if (err)
592 return err;
593
597 dsa_port_set_tag_protocol(dsa_to_port(ds, port), tag_ops);
594 dsa_port_set_tag_protocol(cpu_dp, tag_ops);
598 }
599
600 /* Now that changing the tag protocol can no longer fail, let's update
601 * the remaining bits which are "duplicated for faster access", and the
602 * bits that depend on the tagger, such as the MTU.
603 */
595 }
596
597 /* Now that changing the tag protocol can no longer fail, let's update
598 * the remaining bits which are "duplicated for faster access", and the
599 * bits that depend on the tagger, such as the MTU.
600 */
604 for (port = 0; port < ds->num_ports; port++) {
605 if (dsa_is_user_port(ds, port)) {
606 struct net_device *slave;
601 dsa_switch_for_each_user_port(dp, ds) {
602 struct net_device *slave = dp->slave;
607
603
608 slave = dsa_to_port(ds, port)->slave;
609 dsa_slave_setup_tagger(slave);
604 dsa_slave_setup_tagger(slave);
610
605
611 /* rtnl_mutex is held in dsa_tree_change_tag_proto */
612 dsa_slave_change_mtu(slave, slave->mtu);
613 }
606 /* rtnl_mutex is held in dsa_tree_change_tag_proto */
607 dsa_slave_change_mtu(slave, slave->mtu);
614 }
615
616 return 0;
617}
618
619static int dsa_switch_mrp_add(struct dsa_switch *ds,
620 struct dsa_notifier_mrp_info *info)
621{

--- 161 unchanged lines hidden ---
608 }
609
610 return 0;
611}
612
613static int dsa_switch_mrp_add(struct dsa_switch *ds,
614 struct dsa_notifier_mrp_info *info)
615{

--- 161 unchanged lines hidden ---