summaryrefslogtreecommitdiffstats
path: root/net/dsa/switch.c
diff options
context:
space:
mode:
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>2017-06-07 18:12:14 -0400
committerDavid S. Miller <davem@davemloft.net>2017-06-08 11:43:31 -0400
commit1ca4aa9cd4cc075e3fddbba80fd2ed2f479bfb22 (patch)
treed3c79e99b95a2b17941c40ee01d3676f99371b69 /net/dsa/switch.c
parentc91498e15bf2cf27fb2743d01bd105201f33a5cb (diff)
net: dsa: check VLAN capability of every switch
Now that the VLAN object is propagated to every switch chip of the switch fabric, we can easily ensure that they all support the required VLAN operations before modifying an entry on a single switch. To achieve that, remove the condition skipping other target switches, and add a bitmap of VLAN members, eventually containing the target port, if we are programming the switch target. This will allow us to easily add other VLAN members, such as the DSA or CPU ports (to introduce cross-chip VLAN support) or the other port members if we want to reduce hardware accesses later. Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa/switch.c')
-rw-r--r--net/dsa/switch.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index d8e5c311ee7c..f235ae1e9777 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -159,19 +159,27 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,
159{ 159{
160 const struct switchdev_obj_port_vlan *vlan = info->vlan; 160 const struct switchdev_obj_port_vlan *vlan = info->vlan;
161 struct switchdev_trans *trans = info->trans; 161 struct switchdev_trans *trans = info->trans;
162 DECLARE_BITMAP(members, ds->num_ports);
163 int port, err;
162 164
163 /* Do not care yet about other switch chips of the fabric */ 165 /* Build a mask of VLAN members */
164 if (ds->index != info->sw_index) 166 bitmap_zero(members, ds->num_ports);
165 return 0; 167 if (ds->index == info->sw_index)
168 set_bit(info->port, members);
166 169
167 if (switchdev_trans_ph_prepare(trans)) { 170 if (switchdev_trans_ph_prepare(trans)) {
168 if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add) 171 if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add)
169 return -EOPNOTSUPP; 172 return -EOPNOTSUPP;
170 173
171 return ds->ops->port_vlan_prepare(ds, info->port, vlan, trans); 174 for_each_set_bit(port, members, ds->num_ports) {
175 err = ds->ops->port_vlan_prepare(ds, port, vlan, trans);
176 if (err)
177 return err;
178 }
172 } 179 }
173 180
174 ds->ops->port_vlan_add(ds, info->port, vlan, trans); 181 for_each_set_bit(port, members, ds->num_ports)
182 ds->ops->port_vlan_add(ds, port, vlan, trans);
175 183
176 return 0; 184 return 0;
177} 185}
@@ -181,14 +189,13 @@ static int dsa_switch_vlan_del(struct dsa_switch *ds,
181{ 189{
182 const struct switchdev_obj_port_vlan *vlan = info->vlan; 190 const struct switchdev_obj_port_vlan *vlan = info->vlan;
183 191
184 /* Do not care yet about other switch chips of the fabric */
185 if (ds->index != info->sw_index)
186 return 0;
187
188 if (!ds->ops->port_vlan_del) 192 if (!ds->ops->port_vlan_del)
189 return -EOPNOTSUPP; 193 return -EOPNOTSUPP;
190 194
191 return ds->ops->port_vlan_del(ds, info->port, vlan); 195 if (ds->index == info->sw_index)
196 return ds->ops->port_vlan_del(ds, info->port, vlan);
197
198 return 0;
192} 199}
193 200
194static int dsa_switch_event(struct notifier_block *nb, 201static int dsa_switch_event(struct notifier_block *nb,