Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
[linux-2.6-microblaze.git] / net / dsa / switch.c
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
17 static unsigned int dsa_switch_fastest_ageing_time(struct dsa_switch *ds,
18                                                    unsigned int ageing_time)
19 {
20         int i;
21
22         for (i = 0; i < ds->num_ports; ++i) {
23                 struct dsa_port *dp = dsa_to_port(ds, i);
24
25                 if (dp->ageing_time && dp->ageing_time < ageing_time)
26                         ageing_time = dp->ageing_time;
27         }
28
29         return ageing_time;
30 }
31
32 static 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;
36
37         if (ds->ageing_time_min && ageing_time < ds->ageing_time_min)
38                 return -ERANGE;
39
40         if (ds->ageing_time_max && ageing_time > ds->ageing_time_max)
41                 return -ERANGE;
42
43         /* Program the fastest ageing time in case of multiple bridges */
44         ageing_time = dsa_switch_fastest_ageing_time(ds, ageing_time);
45
46         if (ds->ops->set_ageing_time)
47                 return ds->ops->set_ageing_time(ds, ageing_time);
48
49         return 0;
50 }
51
52 static bool dsa_switch_mtu_match(struct dsa_switch *ds, int port,
53                                  struct dsa_notifier_mtu_info *info)
54 {
55         if (ds->index == info->sw_index)
56                 return (port == info->port) || dsa_is_dsa_port(ds, port);
57
58         if (!info->propagate_upstream)
59                 return false;
60
61         if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
62                 return true;
63
64         return false;
65 }
66
67 static int dsa_switch_mtu(struct dsa_switch *ds,
68                           struct dsa_notifier_mtu_info *info)
69 {
70         int port, ret;
71
72         if (!ds->ops->port_change_mtu)
73                 return -EOPNOTSUPP;
74
75         for (port = 0; port < ds->num_ports; port++) {
76                 if (dsa_switch_mtu_match(ds, port, info)) {
77                         ret = ds->ops->port_change_mtu(ds, port, info->mtu);
78                         if (ret)
79                                 return ret;
80                 }
81         }
82
83         return 0;
84 }
85
86 static int dsa_switch_bridge_join(struct dsa_switch *ds,
87                                   struct dsa_notifier_bridge_info *info)
88 {
89         struct dsa_switch_tree *dst = ds->dst;
90
91         if (dst->index == info->tree_index && ds->index == info->sw_index &&
92             ds->ops->port_bridge_join)
93                 return ds->ops->port_bridge_join(ds, info->port, info->br);
94
95         if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
96             ds->ops->crosschip_bridge_join)
97                 return ds->ops->crosschip_bridge_join(ds, info->tree_index,
98                                                       info->sw_index,
99                                                       info->port, info->br);
100
101         return 0;
102 }
103
104 static int dsa_switch_bridge_leave(struct dsa_switch *ds,
105                                    struct dsa_notifier_bridge_info *info)
106 {
107         bool unset_vlan_filtering = br_vlan_enabled(info->br);
108         struct dsa_switch_tree *dst = ds->dst;
109         struct netlink_ext_ack extack = {0};
110         int err, i;
111
112         if (dst->index == info->tree_index && ds->index == info->sw_index &&
113             ds->ops->port_bridge_join)
114                 ds->ops->port_bridge_leave(ds, info->port, info->br);
115
116         if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
117             ds->ops->crosschip_bridge_join)
118                 ds->ops->crosschip_bridge_leave(ds, info->tree_index,
119                                                 info->sw_index, info->port,
120                                                 info->br);
121
122         /* If the bridge was vlan_filtering, the bridge core doesn't trigger an
123          * event for changing vlan_filtering setting upon slave ports leaving
124          * it. That is a good thing, because that lets us handle it and also
125          * handle the case where the switch's vlan_filtering setting is global
126          * (not per port). When that happens, the correct moment to trigger the
127          * vlan_filtering callback is only when the last port left this bridge.
128          */
129         if (unset_vlan_filtering && ds->vlan_filtering_is_global) {
130                 for (i = 0; i < ds->num_ports; i++) {
131                         if (i == info->port)
132                                 continue;
133                         if (dsa_to_port(ds, i)->bridge_dev == info->br) {
134                                 unset_vlan_filtering = false;
135                                 break;
136                         }
137                 }
138         }
139         if (unset_vlan_filtering) {
140                 err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port),
141                                               false, &extack);
142                 if (extack._msg)
143                         dev_err(ds->dev, "port %d: %s\n", info->port,
144                                 extack._msg);
145                 if (err && err != EOPNOTSUPP)
146                         return err;
147         }
148         return 0;
149 }
150
151 static int dsa_switch_fdb_add(struct dsa_switch *ds,
152                               struct dsa_notifier_fdb_info *info)
153 {
154         int port = dsa_towards_port(ds, info->sw_index, info->port);
155
156         if (!ds->ops->port_fdb_add)
157                 return -EOPNOTSUPP;
158
159         return ds->ops->port_fdb_add(ds, port, info->addr, info->vid);
160 }
161
162 static int dsa_switch_fdb_del(struct dsa_switch *ds,
163                               struct dsa_notifier_fdb_info *info)
164 {
165         int port = dsa_towards_port(ds, info->sw_index, info->port);
166
167         if (!ds->ops->port_fdb_del)
168                 return -EOPNOTSUPP;
169
170         return ds->ops->port_fdb_del(ds, port, info->addr, info->vid);
171 }
172
173 static int dsa_switch_hsr_join(struct dsa_switch *ds,
174                                struct dsa_notifier_hsr_info *info)
175 {
176         if (ds->index == info->sw_index && ds->ops->port_hsr_join)
177                 return ds->ops->port_hsr_join(ds, info->port, info->hsr);
178
179         return -EOPNOTSUPP;
180 }
181
182 static int dsa_switch_hsr_leave(struct dsa_switch *ds,
183                                 struct dsa_notifier_hsr_info *info)
184 {
185         if (ds->index == info->sw_index && ds->ops->port_hsr_leave)
186                 return ds->ops->port_hsr_leave(ds, info->port, info->hsr);
187
188         return -EOPNOTSUPP;
189 }
190
191 static int dsa_switch_lag_change(struct dsa_switch *ds,
192                                  struct dsa_notifier_lag_info *info)
193 {
194         if (ds->index == info->sw_index && ds->ops->port_lag_change)
195                 return ds->ops->port_lag_change(ds, info->port);
196
197         if (ds->index != info->sw_index && ds->ops->crosschip_lag_change)
198                 return ds->ops->crosschip_lag_change(ds, info->sw_index,
199                                                      info->port);
200
201         return 0;
202 }
203
204 static int dsa_switch_lag_join(struct dsa_switch *ds,
205                                struct dsa_notifier_lag_info *info)
206 {
207         if (ds->index == info->sw_index && ds->ops->port_lag_join)
208                 return ds->ops->port_lag_join(ds, info->port, info->lag,
209                                               info->info);
210
211         if (ds->index != info->sw_index && ds->ops->crosschip_lag_join)
212                 return ds->ops->crosschip_lag_join(ds, info->sw_index,
213                                                    info->port, info->lag,
214                                                    info->info);
215
216         return 0;
217 }
218
219 static int dsa_switch_lag_leave(struct dsa_switch *ds,
220                                 struct dsa_notifier_lag_info *info)
221 {
222         if (ds->index == info->sw_index && ds->ops->port_lag_leave)
223                 return ds->ops->port_lag_leave(ds, info->port, info->lag);
224
225         if (ds->index != info->sw_index && ds->ops->crosschip_lag_leave)
226                 return ds->ops->crosschip_lag_leave(ds, info->sw_index,
227                                                     info->port, info->lag);
228
229         return 0;
230 }
231
232 static bool dsa_switch_mdb_match(struct dsa_switch *ds, int port,
233                                  struct dsa_notifier_mdb_info *info)
234 {
235         if (ds->index == info->sw_index && port == info->port)
236                 return true;
237
238         if (dsa_is_dsa_port(ds, port))
239                 return true;
240
241         return false;
242 }
243
244 static int dsa_switch_mdb_add(struct dsa_switch *ds,
245                               struct dsa_notifier_mdb_info *info)
246 {
247         int err = 0;
248         int port;
249
250         if (!ds->ops->port_mdb_add)
251                 return -EOPNOTSUPP;
252
253         for (port = 0; port < ds->num_ports; port++) {
254                 if (dsa_switch_mdb_match(ds, port, info)) {
255                         err = ds->ops->port_mdb_add(ds, port, info->mdb);
256                         if (err)
257                                 break;
258                 }
259         }
260
261         return err;
262 }
263
264 static int dsa_switch_mdb_del(struct dsa_switch *ds,
265                               struct dsa_notifier_mdb_info *info)
266 {
267         if (!ds->ops->port_mdb_del)
268                 return -EOPNOTSUPP;
269
270         if (ds->index == info->sw_index)
271                 return ds->ops->port_mdb_del(ds, info->port, info->mdb);
272
273         return 0;
274 }
275
276 static bool dsa_switch_vlan_match(struct dsa_switch *ds, int port,
277                                   struct dsa_notifier_vlan_info *info)
278 {
279         if (ds->index == info->sw_index && port == info->port)
280                 return true;
281
282         if (dsa_is_dsa_port(ds, port))
283                 return true;
284
285         return false;
286 }
287
288 static int dsa_switch_vlan_add(struct dsa_switch *ds,
289                                struct dsa_notifier_vlan_info *info)
290 {
291         int port, err;
292
293         if (!ds->ops->port_vlan_add)
294                 return -EOPNOTSUPP;
295
296         for (port = 0; port < ds->num_ports; port++) {
297                 if (dsa_switch_vlan_match(ds, port, info)) {
298                         err = ds->ops->port_vlan_add(ds, port, info->vlan,
299                                                      info->extack);
300                         if (err)
301                                 return err;
302                 }
303         }
304
305         return 0;
306 }
307
308 static int dsa_switch_vlan_del(struct dsa_switch *ds,
309                                struct dsa_notifier_vlan_info *info)
310 {
311         if (!ds->ops->port_vlan_del)
312                 return -EOPNOTSUPP;
313
314         if (ds->index == info->sw_index)
315                 return ds->ops->port_vlan_del(ds, info->port, info->vlan);
316
317         /* Do not deprogram the DSA links as they may be used as conduit
318          * for other VLAN members in the fabric.
319          */
320         return 0;
321 }
322
323 static bool dsa_switch_tag_proto_match(struct dsa_switch *ds, int port,
324                                        struct dsa_notifier_tag_proto_info *info)
325 {
326         if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
327                 return true;
328
329         return false;
330 }
331
332 static int dsa_switch_change_tag_proto(struct dsa_switch *ds,
333                                        struct dsa_notifier_tag_proto_info *info)
334 {
335         const struct dsa_device_ops *tag_ops = info->tag_ops;
336         int port, err;
337
338         if (!ds->ops->change_tag_protocol)
339                 return -EOPNOTSUPP;
340
341         ASSERT_RTNL();
342
343         for (port = 0; port < ds->num_ports; port++) {
344                 if (dsa_switch_tag_proto_match(ds, port, info)) {
345                         err = ds->ops->change_tag_protocol(ds, port,
346                                                            tag_ops->proto);
347                         if (err)
348                                 return err;
349
350                         if (dsa_is_cpu_port(ds, port))
351                                 dsa_port_set_tag_protocol(dsa_to_port(ds, port),
352                                                           tag_ops);
353                 }
354         }
355
356         /* Now that changing the tag protocol can no longer fail, let's update
357          * the remaining bits which are "duplicated for faster access", and the
358          * bits that depend on the tagger, such as the MTU.
359          */
360         for (port = 0; port < ds->num_ports; port++) {
361                 if (dsa_is_user_port(ds, port)) {
362                         struct net_device *slave;
363
364                         slave = dsa_to_port(ds, port)->slave;
365                         dsa_slave_setup_tagger(slave);
366
367                         /* rtnl_mutex is held in dsa_tree_change_tag_proto */
368                         dsa_slave_change_mtu(slave, slave->mtu);
369                 }
370         }
371
372         return 0;
373 }
374
375 static bool dsa_switch_mrp_match(struct dsa_switch *ds, int port,
376                                  struct dsa_notifier_mrp_info *info)
377 {
378         if (ds->index == info->sw_index && port == info->port)
379                 return true;
380
381         if (dsa_is_dsa_port(ds, port))
382                 return true;
383
384         return false;
385 }
386
387 static int dsa_switch_mrp_add(struct dsa_switch *ds,
388                               struct dsa_notifier_mrp_info *info)
389 {
390         int err = 0;
391         int port;
392
393         if (!ds->ops->port_mrp_add)
394                 return -EOPNOTSUPP;
395
396         for (port = 0; port < ds->num_ports; port++) {
397                 if (dsa_switch_mrp_match(ds, port, info)) {
398                         err = ds->ops->port_mrp_add(ds, port, info->mrp);
399                         if (err)
400                                 break;
401                 }
402         }
403
404         return err;
405 }
406
407 static int dsa_switch_mrp_del(struct dsa_switch *ds,
408                               struct dsa_notifier_mrp_info *info)
409 {
410         if (!ds->ops->port_mrp_del)
411                 return -EOPNOTSUPP;
412
413         if (ds->index == info->sw_index)
414                 return ds->ops->port_mrp_del(ds, info->port, info->mrp);
415
416         return 0;
417 }
418
419 static bool
420 dsa_switch_mrp_ring_role_match(struct dsa_switch *ds, int port,
421                                struct dsa_notifier_mrp_ring_role_info *info)
422 {
423         if (ds->index == info->sw_index && port == info->port)
424                 return true;
425
426         if (dsa_is_dsa_port(ds, port))
427                 return true;
428
429         return false;
430 }
431
432 static int
433 dsa_switch_mrp_add_ring_role(struct dsa_switch *ds,
434                              struct dsa_notifier_mrp_ring_role_info *info)
435 {
436         int err = 0;
437         int port;
438
439         if (!ds->ops->port_mrp_add)
440                 return -EOPNOTSUPP;
441
442         for (port = 0; port < ds->num_ports; port++) {
443                 if (dsa_switch_mrp_ring_role_match(ds, port, info)) {
444                         err = ds->ops->port_mrp_add_ring_role(ds, port,
445                                                               info->mrp);
446                         if (err)
447                                 break;
448                 }
449         }
450
451         return err;
452 }
453
454 static int
455 dsa_switch_mrp_del_ring_role(struct dsa_switch *ds,
456                              struct dsa_notifier_mrp_ring_role_info *info)
457 {
458         if (!ds->ops->port_mrp_del)
459                 return -EOPNOTSUPP;
460
461         if (ds->index == info->sw_index)
462                 return ds->ops->port_mrp_del_ring_role(ds, info->port,
463                                                        info->mrp);
464
465         return 0;
466 }
467
468 static int dsa_switch_event(struct notifier_block *nb,
469                             unsigned long event, void *info)
470 {
471         struct dsa_switch *ds = container_of(nb, struct dsa_switch, nb);
472         int err;
473
474         switch (event) {
475         case DSA_NOTIFIER_AGEING_TIME:
476                 err = dsa_switch_ageing_time(ds, info);
477                 break;
478         case DSA_NOTIFIER_BRIDGE_JOIN:
479                 err = dsa_switch_bridge_join(ds, info);
480                 break;
481         case DSA_NOTIFIER_BRIDGE_LEAVE:
482                 err = dsa_switch_bridge_leave(ds, info);
483                 break;
484         case DSA_NOTIFIER_FDB_ADD:
485                 err = dsa_switch_fdb_add(ds, info);
486                 break;
487         case DSA_NOTIFIER_FDB_DEL:
488                 err = dsa_switch_fdb_del(ds, info);
489                 break;
490         case DSA_NOTIFIER_HSR_JOIN:
491                 err = dsa_switch_hsr_join(ds, info);
492                 break;
493         case DSA_NOTIFIER_HSR_LEAVE:
494                 err = dsa_switch_hsr_leave(ds, info);
495                 break;
496         case DSA_NOTIFIER_LAG_CHANGE:
497                 err = dsa_switch_lag_change(ds, info);
498                 break;
499         case DSA_NOTIFIER_LAG_JOIN:
500                 err = dsa_switch_lag_join(ds, info);
501                 break;
502         case DSA_NOTIFIER_LAG_LEAVE:
503                 err = dsa_switch_lag_leave(ds, info);
504                 break;
505         case DSA_NOTIFIER_MDB_ADD:
506                 err = dsa_switch_mdb_add(ds, info);
507                 break;
508         case DSA_NOTIFIER_MDB_DEL:
509                 err = dsa_switch_mdb_del(ds, info);
510                 break;
511         case DSA_NOTIFIER_VLAN_ADD:
512                 err = dsa_switch_vlan_add(ds, info);
513                 break;
514         case DSA_NOTIFIER_VLAN_DEL:
515                 err = dsa_switch_vlan_del(ds, info);
516                 break;
517         case DSA_NOTIFIER_MTU:
518                 err = dsa_switch_mtu(ds, info);
519                 break;
520         case DSA_NOTIFIER_TAG_PROTO:
521                 err = dsa_switch_change_tag_proto(ds, info);
522                 break;
523         case DSA_NOTIFIER_MRP_ADD:
524                 err = dsa_switch_mrp_add(ds, info);
525                 break;
526         case DSA_NOTIFIER_MRP_DEL:
527                 err = dsa_switch_mrp_del(ds, info);
528                 break;
529         case DSA_NOTIFIER_MRP_ADD_RING_ROLE:
530                 err = dsa_switch_mrp_add_ring_role(ds, info);
531                 break;
532         case DSA_NOTIFIER_MRP_DEL_RING_ROLE:
533                 err = dsa_switch_mrp_del_ring_role(ds, info);
534                 break;
535         default:
536                 err = -EOPNOTSUPP;
537                 break;
538         }
539
540         if (err)
541                 dev_dbg(ds->dev, "breaking chain for DSA event %lu (%d)\n",
542                         event, err);
543
544         return notifier_from_errno(err);
545 }
546
547 int dsa_switch_register_notifier(struct dsa_switch *ds)
548 {
549         ds->nb.notifier_call = dsa_switch_event;
550
551         return raw_notifier_chain_register(&ds->dst->nh, &ds->nb);
552 }
553
554 void dsa_switch_unregister_notifier(struct dsa_switch *ds)
555 {
556         int err;
557
558         err = raw_notifier_chain_unregister(&ds->dst->nh, &ds->nb);
559         if (err)
560                 dev_err(ds->dev, "failed to unregister notifier (%d)\n", err);
561 }