summaryrefslogtreecommitdiffstats
path: root/net/dsa/switch.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dsa/switch.c')
-rw-r--r--net/dsa/switch.c132
1 files changed, 59 insertions, 73 deletions
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 09d9286b27cc..489eb7b430a4 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -128,57 +128,51 @@ static int dsa_switch_fdb_del(struct dsa_switch *ds,
128 return ds->ops->port_fdb_del(ds, port, info->addr, info->vid); 128 return ds->ops->port_fdb_del(ds, port, info->addr, info->vid);
129} 129}
130 130
131static int 131static bool dsa_switch_mdb_match(struct dsa_switch *ds, int port,
132dsa_switch_mdb_prepare_bitmap(struct dsa_switch *ds, 132 struct dsa_notifier_mdb_info *info)
133 const struct switchdev_obj_port_mdb *mdb, 133{
134 const unsigned long *bitmap) 134 if (ds->index == info->sw_index && port == info->port)
135 return true;
136
137 if (dsa_is_dsa_port(ds, port))
138 return true;
139
140 return false;
141}
142
143static int dsa_switch_mdb_prepare(struct dsa_switch *ds,
144 struct dsa_notifier_mdb_info *info)
135{ 145{
136 int port, err; 146 int port, err;
137 147
138 if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add) 148 if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add)
139 return -EOPNOTSUPP; 149 return -EOPNOTSUPP;
140 150
141 for_each_set_bit(port, bitmap, ds->num_ports) { 151 for (port = 0; port < ds->num_ports; port++) {
142 err = ds->ops->port_mdb_prepare(ds, port, mdb); 152 if (dsa_switch_mdb_match(ds, port, info)) {
143 if (err) 153 err = ds->ops->port_mdb_prepare(ds, port, info->mdb);
144 return err; 154 if (err)
155 return err;
156 }
145 } 157 }
146 158
147 return 0; 159 return 0;
148} 160}
149 161
150static void dsa_switch_mdb_add_bitmap(struct dsa_switch *ds,
151 const struct switchdev_obj_port_mdb *mdb,
152 const unsigned long *bitmap)
153{
154 int port;
155
156 if (!ds->ops->port_mdb_add)
157 return;
158
159 for_each_set_bit(port, bitmap, ds->num_ports)
160 ds->ops->port_mdb_add(ds, port, mdb);
161}
162
163static int dsa_switch_mdb_add(struct dsa_switch *ds, 162static int dsa_switch_mdb_add(struct dsa_switch *ds,
164 struct dsa_notifier_mdb_info *info) 163 struct dsa_notifier_mdb_info *info)
165{ 164{
166 const struct switchdev_obj_port_mdb *mdb = info->mdb;
167 struct switchdev_trans *trans = info->trans;
168 int port; 165 int port;
169 166
170 /* Build a mask of Multicast group members */ 167 if (switchdev_trans_ph_prepare(info->trans))
171 bitmap_zero(ds->bitmap, ds->num_ports); 168 return dsa_switch_mdb_prepare(ds, info);
172 if (ds->index == info->sw_index)
173 set_bit(info->port, ds->bitmap);
174 for (port = 0; port < ds->num_ports; port++)
175 if (dsa_is_dsa_port(ds, port))
176 set_bit(port, ds->bitmap);
177 169
178 if (switchdev_trans_ph_prepare(trans)) 170 if (!ds->ops->port_mdb_add)
179 return dsa_switch_mdb_prepare_bitmap(ds, mdb, ds->bitmap); 171 return 0;
180 172
181 dsa_switch_mdb_add_bitmap(ds, mdb, ds->bitmap); 173 for (port = 0; port < ds->num_ports; port++)
174 if (dsa_switch_mdb_match(ds, port, info))
175 ds->ops->port_mdb_add(ds, port, info->mdb);
182 176
183 return 0; 177 return 0;
184} 178}
@@ -186,13 +180,11 @@ static int dsa_switch_mdb_add(struct dsa_switch *ds,
186static int dsa_switch_mdb_del(struct dsa_switch *ds, 180static int dsa_switch_mdb_del(struct dsa_switch *ds,
187 struct dsa_notifier_mdb_info *info) 181 struct dsa_notifier_mdb_info *info)
188{ 182{
189 const struct switchdev_obj_port_mdb *mdb = info->mdb;
190
191 if (!ds->ops->port_mdb_del) 183 if (!ds->ops->port_mdb_del)
192 return -EOPNOTSUPP; 184 return -EOPNOTSUPP;
193 185
194 if (ds->index == info->sw_index) 186 if (ds->index == info->sw_index)
195 return ds->ops->port_mdb_del(ds, info->port, mdb); 187 return ds->ops->port_mdb_del(ds, info->port, info->mdb);
196 188
197 return 0; 189 return 0;
198} 190}
@@ -234,59 +226,55 @@ static int dsa_port_vlan_check(struct dsa_switch *ds, int port,
234 (void *)vlan); 226 (void *)vlan);
235} 227}
236 228
237static int 229static bool dsa_switch_vlan_match(struct dsa_switch *ds, int port,
238dsa_switch_vlan_prepare_bitmap(struct dsa_switch *ds, 230 struct dsa_notifier_vlan_info *info)
239 const struct switchdev_obj_port_vlan *vlan, 231{
240 const unsigned long *bitmap) 232 if (ds->index == info->sw_index && port == info->port)
233 return true;
234
235 if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
236 return true;
237
238 return false;
239}
240
241static int dsa_switch_vlan_prepare(struct dsa_switch *ds,
242 struct dsa_notifier_vlan_info *info)
241{ 243{
242 int port, err; 244 int port, err;
243 245
244 if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add) 246 if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add)
245 return -EOPNOTSUPP; 247 return -EOPNOTSUPP;
246 248
247 for_each_set_bit(port, bitmap, ds->num_ports) { 249 for (port = 0; port < ds->num_ports; port++) {
248 err = dsa_port_vlan_check(ds, port, vlan); 250 if (dsa_switch_vlan_match(ds, port, info)) {
249 if (err) 251 err = dsa_port_vlan_check(ds, port, info->vlan);
250 return err; 252 if (err)
253 return err;
251 254
252 err = ds->ops->port_vlan_prepare(ds, port, vlan); 255 err = ds->ops->port_vlan_prepare(ds, port, info->vlan);
253 if (err) 256 if (err)
254 return err; 257 return err;
258 }
255 } 259 }
256 260
257 return 0; 261 return 0;
258} 262}
259 263
260static void
261dsa_switch_vlan_add_bitmap(struct dsa_switch *ds,
262 const struct switchdev_obj_port_vlan *vlan,
263 const unsigned long *bitmap)
264{
265 int port;
266
267 for_each_set_bit(port, bitmap, ds->num_ports)
268 ds->ops->port_vlan_add(ds, port, vlan);
269}
270
271static int dsa_switch_vlan_add(struct dsa_switch *ds, 264static int dsa_switch_vlan_add(struct dsa_switch *ds,
272 struct dsa_notifier_vlan_info *info) 265 struct dsa_notifier_vlan_info *info)
273{ 266{
274 const struct switchdev_obj_port_vlan *vlan = info->vlan;
275 struct switchdev_trans *trans = info->trans;
276 int port; 267 int port;
277 268
278 /* Build a mask of VLAN members */ 269 if (switchdev_trans_ph_prepare(info->trans))
279 bitmap_zero(ds->bitmap, ds->num_ports); 270 return dsa_switch_vlan_prepare(ds, info);
280 if (ds->index == info->sw_index)
281 set_bit(info->port, ds->bitmap);
282 for (port = 0; port < ds->num_ports; port++)
283 if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
284 set_bit(port, ds->bitmap);
285 271
286 if (switchdev_trans_ph_prepare(trans)) 272 if (!ds->ops->port_vlan_add)
287 return dsa_switch_vlan_prepare_bitmap(ds, vlan, ds->bitmap); 273 return 0;
288 274
289 dsa_switch_vlan_add_bitmap(ds, vlan, ds->bitmap); 275 for (port = 0; port < ds->num_ports; port++)
276 if (dsa_switch_vlan_match(ds, port, info))
277 ds->ops->port_vlan_add(ds, port, info->vlan);
290 278
291 return 0; 279 return 0;
292} 280}
@@ -294,13 +282,11 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,
294static int dsa_switch_vlan_del(struct dsa_switch *ds, 282static int dsa_switch_vlan_del(struct dsa_switch *ds,
295 struct dsa_notifier_vlan_info *info) 283 struct dsa_notifier_vlan_info *info)
296{ 284{
297 const struct switchdev_obj_port_vlan *vlan = info->vlan;
298
299 if (!ds->ops->port_vlan_del) 285 if (!ds->ops->port_vlan_del)
300 return -EOPNOTSUPP; 286 return -EOPNOTSUPP;
301 287
302 if (ds->index == info->sw_index) 288 if (ds->index == info->sw_index)
303 return ds->ops->port_vlan_del(ds, info->port, vlan); 289 return ds->ops->port_vlan_del(ds, info->port, info->vlan);
304 290
305 return 0; 291 return 0;
306} 292}