1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
3
4#include <linux/if_bridge.h>
5#include <linux/if_vlan.h>
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/notifier.h>
9#include <net/netevent.h>
10#include <net/switchdev.h>
11
12#include "prestera.h"
13#include "prestera_hw.h"
14#include "prestera_switchdev.h"
15
16#define PRESTERA_VID_ALL (0xffff)
17
18#define PRESTERA_DEFAULT_AGEING_TIME_MS 300000
19#define PRESTERA_MAX_AGEING_TIME_MS 1000000000
20#define PRESTERA_MIN_AGEING_TIME_MS 32000
21
22struct prestera_fdb_event_work {
23 struct work_struct work;
24 struct switchdev_notifier_fdb_info fdb_info;
25 struct net_device *dev;
26 unsigned long event;
27};
28
29struct prestera_switchdev {
30 struct prestera_switch *sw;
31 struct list_head bridge_list;
32 bool bridge_8021q_exists;
33 struct notifier_block swdev_nb_blk;
34 struct notifier_block swdev_nb;
35};
36
37struct prestera_bridge {
38 struct list_head head;
39 struct net_device *dev;
40 struct prestera_switchdev *swdev;
41 struct list_head port_list;
42 struct list_head br_mdb_entry_list;
43 bool mrouter_exist;
44 bool vlan_enabled;
45 bool multicast_enabled;
46 u16 bridge_id;
47};
48
49struct prestera_bridge_port {
50 struct list_head head;
51 struct net_device *dev;
52 struct prestera_bridge *bridge;
53 struct list_head vlan_list;
54 struct list_head br_mdb_port_list;
55 refcount_t ref_count;
56 unsigned long flags;
57 bool mrouter;
58 u8 stp_state;
59};
60
61struct prestera_bridge_vlan {
62 struct list_head head;
63 struct list_head port_vlan_list;
64 u16 vid;
65};
66
67struct prestera_port_vlan {
68 struct list_head br_vlan_head;
69 struct list_head port_head;
70 struct prestera_port *port;
71 struct prestera_bridge_port *br_port;
72 u16 vid;
73};
74
75struct prestera_br_mdb_port {
76 struct prestera_bridge_port *br_port;
77 struct list_head br_mdb_port_node;
78};
79
80/* Software representation of MDB table. */
81struct prestera_br_mdb_entry {
82 struct prestera_bridge *bridge;
83 struct prestera_mdb_entry *mdb;
84 struct list_head br_mdb_port_list;
85 struct list_head br_mdb_entry_node;
86 bool enabled;
87};
88
89static struct workqueue_struct *swdev_wq;
90
91static void prestera_bridge_port_put(struct prestera_bridge_port *br_port);
92
93static int prestera_port_vid_stp_set(struct prestera_port *port, u16 vid,
94 u8 state);
95
96static struct prestera_bridge *
97prestera_bridge_find(const struct prestera_switch *sw,
98 const struct net_device *br_dev)
99{
100 struct prestera_bridge *bridge;
101
102 list_for_each_entry(bridge, &sw->swdev->bridge_list, head)
103 if (bridge->dev == br_dev)
104 return bridge;
105
106 return NULL;
107}
108
109static struct prestera_bridge_port *
110__prestera_bridge_port_find(const struct prestera_bridge *bridge,
111 const struct net_device *brport_dev)
112{
113 struct prestera_bridge_port *br_port;
114
115 list_for_each_entry(br_port, &bridge->port_list, head)
116 if (br_port->dev == brport_dev)
117 return br_port;
118
119 return NULL;
120}
121
122static struct prestera_bridge_port *
123prestera_bridge_port_find(struct prestera_switch *sw,
124 struct net_device *brport_dev)
125{
126 struct net_device *br_dev = netdev_master_upper_dev_get(dev: brport_dev);
127 struct prestera_bridge *bridge;
128
129 if (!br_dev)
130 return NULL;
131
132 bridge = prestera_bridge_find(sw, br_dev);
133 if (!bridge)
134 return NULL;
135
136 return __prestera_bridge_port_find(bridge, brport_dev);
137}
138
139static void
140prestera_br_port_flags_reset(struct prestera_bridge_port *br_port,
141 struct prestera_port *port)
142{
143 prestera_port_uc_flood_set(port, flood: false);
144 prestera_port_mc_flood_set(port, flood: false);
145 prestera_port_learning_set(port, learn_enable: false);
146 prestera_port_br_locked_set(port, br_locked: false);
147}
148
149static int prestera_br_port_flags_set(struct prestera_bridge_port *br_port,
150 struct prestera_port *port)
151{
152 int err;
153
154 err = prestera_port_uc_flood_set(port, flood: br_port->flags & BR_FLOOD);
155 if (err)
156 goto err_out;
157
158 err = prestera_port_mc_flood_set(port, flood: br_port->flags & BR_MCAST_FLOOD);
159 if (err)
160 goto err_out;
161
162 err = prestera_port_learning_set(port, learn_enable: br_port->flags & BR_LEARNING);
163 if (err)
164 goto err_out;
165
166 err = prestera_port_br_locked_set(port,
167 br_locked: br_port->flags & BR_PORT_LOCKED);
168 if (err)
169 goto err_out;
170
171 return 0;
172
173err_out:
174 prestera_br_port_flags_reset(br_port, port);
175 return err;
176}
177
178static struct prestera_bridge_vlan *
179prestera_bridge_vlan_create(struct prestera_bridge_port *br_port, u16 vid)
180{
181 struct prestera_bridge_vlan *br_vlan;
182
183 br_vlan = kzalloc(size: sizeof(*br_vlan), GFP_KERNEL);
184 if (!br_vlan)
185 return NULL;
186
187 INIT_LIST_HEAD(list: &br_vlan->port_vlan_list);
188 br_vlan->vid = vid;
189 list_add(new: &br_vlan->head, head: &br_port->vlan_list);
190
191 return br_vlan;
192}
193
194static void prestera_bridge_vlan_destroy(struct prestera_bridge_vlan *br_vlan)
195{
196 list_del(entry: &br_vlan->head);
197 WARN_ON(!list_empty(&br_vlan->port_vlan_list));
198 kfree(objp: br_vlan);
199}
200
201static struct prestera_bridge_vlan *
202prestera_bridge_vlan_by_vid(struct prestera_bridge_port *br_port, u16 vid)
203{
204 struct prestera_bridge_vlan *br_vlan;
205
206 list_for_each_entry(br_vlan, &br_port->vlan_list, head) {
207 if (br_vlan->vid == vid)
208 return br_vlan;
209 }
210
211 return NULL;
212}
213
214static int prestera_bridge_vlan_port_count(struct prestera_bridge *bridge,
215 u16 vid)
216{
217 struct prestera_bridge_port *br_port;
218 struct prestera_bridge_vlan *br_vlan;
219 int count = 0;
220
221 list_for_each_entry(br_port, &bridge->port_list, head) {
222 list_for_each_entry(br_vlan, &br_port->vlan_list, head) {
223 if (br_vlan->vid == vid) {
224 count += 1;
225 break;
226 }
227 }
228 }
229
230 return count;
231}
232
233static void prestera_bridge_vlan_put(struct prestera_bridge_vlan *br_vlan)
234{
235 if (list_empty(head: &br_vlan->port_vlan_list))
236 prestera_bridge_vlan_destroy(br_vlan);
237}
238
239static struct prestera_port_vlan *
240prestera_port_vlan_by_vid(struct prestera_port *port, u16 vid)
241{
242 struct prestera_port_vlan *port_vlan;
243
244 list_for_each_entry(port_vlan, &port->vlans_list, port_head) {
245 if (port_vlan->vid == vid)
246 return port_vlan;
247 }
248
249 return NULL;
250}
251
252static struct prestera_port_vlan *
253prestera_port_vlan_create(struct prestera_port *port, u16 vid, bool untagged)
254{
255 struct prestera_port_vlan *port_vlan;
256 int err;
257
258 port_vlan = prestera_port_vlan_by_vid(port, vid);
259 if (port_vlan)
260 return ERR_PTR(error: -EEXIST);
261
262 err = prestera_hw_vlan_port_set(port, vid, is_member: true, untagged);
263 if (err)
264 return ERR_PTR(error: err);
265
266 port_vlan = kzalloc(size: sizeof(*port_vlan), GFP_KERNEL);
267 if (!port_vlan) {
268 err = -ENOMEM;
269 goto err_port_vlan_alloc;
270 }
271
272 port_vlan->port = port;
273 port_vlan->vid = vid;
274
275 list_add(new: &port_vlan->port_head, head: &port->vlans_list);
276
277 return port_vlan;
278
279err_port_vlan_alloc:
280 prestera_hw_vlan_port_set(port, vid, is_member: false, untagged: false);
281 return ERR_PTR(error: err);
282}
283
284static int prestera_fdb_add(struct prestera_port *port,
285 const unsigned char *mac, u16 vid, bool dynamic)
286{
287 if (prestera_port_is_lag_member(port))
288 return prestera_hw_lag_fdb_add(sw: port->sw, lag_id: prestera_port_lag_id(port),
289 mac, vid, dynamic);
290
291 return prestera_hw_fdb_add(port, mac, vid, dynamic);
292}
293
294static int prestera_fdb_del(struct prestera_port *port,
295 const unsigned char *mac, u16 vid)
296{
297 if (prestera_port_is_lag_member(port))
298 return prestera_hw_lag_fdb_del(sw: port->sw, lag_id: prestera_port_lag_id(port),
299 mac, vid);
300 else
301 return prestera_hw_fdb_del(port, mac, vid);
302}
303
304static int prestera_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
305 u32 mode)
306{
307 if (prestera_port_is_lag_member(port))
308 return prestera_hw_fdb_flush_lag_vlan(sw: port->sw, lag_id: prestera_port_lag_id(port),
309 vid, mode);
310 else
311 return prestera_hw_fdb_flush_port_vlan(port, vid, mode);
312}
313
314static int prestera_fdb_flush_port(struct prestera_port *port, u32 mode)
315{
316 if (prestera_port_is_lag_member(port))
317 return prestera_hw_fdb_flush_lag(sw: port->sw, lag_id: prestera_port_lag_id(port),
318 mode);
319 else
320 return prestera_hw_fdb_flush_port(port, mode);
321}
322
323static void
324prestera_mdb_port_del(struct prestera_mdb_entry *mdb,
325 struct net_device *orig_dev)
326{
327 struct prestera_flood_domain *fl_domain = mdb->flood_domain;
328 struct prestera_flood_domain_port *flood_domain_port;
329
330 flood_domain_port = prestera_flood_domain_port_find(flood_domain: fl_domain,
331 dev: orig_dev,
332 vid: mdb->vid);
333 if (flood_domain_port)
334 prestera_flood_domain_port_destroy(port: flood_domain_port);
335}
336
337static void
338prestera_br_mdb_entry_put(struct prestera_br_mdb_entry *br_mdb)
339{
340 struct prestera_bridge_port *br_port;
341
342 if (list_empty(head: &br_mdb->br_mdb_port_list)) {
343 list_for_each_entry(br_port, &br_mdb->bridge->port_list, head)
344 prestera_mdb_port_del(mdb: br_mdb->mdb, orig_dev: br_port->dev);
345
346 prestera_mdb_entry_destroy(mdb_entry: br_mdb->mdb);
347 list_del(entry: &br_mdb->br_mdb_entry_node);
348 kfree(objp: br_mdb);
349 }
350}
351
352static void
353prestera_br_mdb_port_del(struct prestera_br_mdb_entry *br_mdb,
354 struct prestera_bridge_port *br_port)
355{
356 struct prestera_br_mdb_port *br_mdb_port, *tmp;
357
358 list_for_each_entry_safe(br_mdb_port, tmp, &br_mdb->br_mdb_port_list,
359 br_mdb_port_node) {
360 if (br_mdb_port->br_port == br_port) {
361 list_del(entry: &br_mdb_port->br_mdb_port_node);
362 kfree(objp: br_mdb_port);
363 }
364 }
365}
366
367static void
368prestera_mdb_flush_bridge_port(struct prestera_bridge_port *br_port)
369{
370 struct prestera_br_mdb_port *br_mdb_port, *tmp_port;
371 struct prestera_br_mdb_entry *br_mdb, *br_mdb_tmp;
372 struct prestera_bridge *br_dev = br_port->bridge;
373
374 list_for_each_entry_safe(br_mdb, br_mdb_tmp, &br_dev->br_mdb_entry_list,
375 br_mdb_entry_node) {
376 list_for_each_entry_safe(br_mdb_port, tmp_port,
377 &br_mdb->br_mdb_port_list,
378 br_mdb_port_node) {
379 prestera_mdb_port_del(mdb: br_mdb->mdb,
380 orig_dev: br_mdb_port->br_port->dev);
381 prestera_br_mdb_port_del(br_mdb, br_port: br_mdb_port->br_port);
382 }
383 prestera_br_mdb_entry_put(br_mdb);
384 }
385}
386
387static void
388prestera_port_vlan_bridge_leave(struct prestera_port_vlan *port_vlan)
389{
390 u32 fdb_flush_mode = PRESTERA_FDB_FLUSH_MODE_DYNAMIC;
391 struct prestera_port *port = port_vlan->port;
392 struct prestera_bridge_vlan *br_vlan;
393 struct prestera_bridge_port *br_port;
394 bool last_port, last_vlan;
395 u16 vid = port_vlan->vid;
396 int port_count;
397
398 br_port = port_vlan->br_port;
399 port_count = prestera_bridge_vlan_port_count(bridge: br_port->bridge, vid);
400 br_vlan = prestera_bridge_vlan_by_vid(br_port, vid);
401
402 last_vlan = list_is_singular(head: &br_port->vlan_list);
403 last_port = port_count == 1;
404
405 if (last_vlan)
406 prestera_fdb_flush_port(port, mode: fdb_flush_mode);
407 else if (last_port)
408 prestera_hw_fdb_flush_vlan(sw: port->sw, vid, mode: fdb_flush_mode);
409 else
410 prestera_fdb_flush_port_vlan(port, vid, mode: fdb_flush_mode);
411
412 prestera_mdb_flush_bridge_port(br_port);
413
414 list_del(entry: &port_vlan->br_vlan_head);
415 prestera_bridge_vlan_put(br_vlan);
416 prestera_bridge_port_put(br_port);
417 port_vlan->br_port = NULL;
418}
419
420static void prestera_port_vlan_destroy(struct prestera_port_vlan *port_vlan)
421{
422 struct prestera_port *port = port_vlan->port;
423 u16 vid = port_vlan->vid;
424
425 if (port_vlan->br_port)
426 prestera_port_vlan_bridge_leave(port_vlan);
427
428 prestera_hw_vlan_port_set(port, vid, is_member: false, untagged: false);
429 list_del(entry: &port_vlan->port_head);
430 kfree(objp: port_vlan);
431}
432
433static struct prestera_bridge *
434prestera_bridge_create(struct prestera_switchdev *swdev, struct net_device *dev)
435{
436 bool vlan_enabled = br_vlan_enabled(dev);
437 struct prestera_bridge *bridge;
438 u16 bridge_id;
439 int err;
440
441 if (vlan_enabled && swdev->bridge_8021q_exists) {
442 netdev_err(dev, format: "Only one VLAN-aware bridge is supported\n");
443 return ERR_PTR(error: -EINVAL);
444 }
445
446 bridge = kzalloc(size: sizeof(*bridge), GFP_KERNEL);
447 if (!bridge)
448 return ERR_PTR(error: -ENOMEM);
449
450 if (vlan_enabled) {
451 swdev->bridge_8021q_exists = true;
452 } else {
453 err = prestera_hw_bridge_create(sw: swdev->sw, bridge_id: &bridge_id);
454 if (err) {
455 kfree(objp: bridge);
456 return ERR_PTR(error: err);
457 }
458
459 bridge->bridge_id = bridge_id;
460 }
461
462 bridge->vlan_enabled = vlan_enabled;
463 bridge->swdev = swdev;
464 bridge->dev = dev;
465 bridge->multicast_enabled = br_multicast_enabled(dev);
466
467 INIT_LIST_HEAD(list: &bridge->port_list);
468 INIT_LIST_HEAD(list: &bridge->br_mdb_entry_list);
469
470 list_add(new: &bridge->head, head: &swdev->bridge_list);
471
472 return bridge;
473}
474
475static void prestera_bridge_destroy(struct prestera_bridge *bridge)
476{
477 struct prestera_switchdev *swdev = bridge->swdev;
478
479 list_del(entry: &bridge->head);
480
481 if (bridge->vlan_enabled)
482 swdev->bridge_8021q_exists = false;
483 else
484 prestera_hw_bridge_delete(sw: swdev->sw, bridge_id: bridge->bridge_id);
485
486 WARN_ON(!list_empty(&bridge->br_mdb_entry_list));
487 WARN_ON(!list_empty(&bridge->port_list));
488 kfree(objp: bridge);
489}
490
491static void prestera_bridge_put(struct prestera_bridge *bridge)
492{
493 if (list_empty(head: &bridge->port_list))
494 prestera_bridge_destroy(bridge);
495}
496
497static
498struct prestera_bridge *prestera_bridge_by_dev(struct prestera_switchdev *swdev,
499 const struct net_device *dev)
500{
501 struct prestera_bridge *bridge;
502
503 list_for_each_entry(bridge, &swdev->bridge_list, head)
504 if (bridge->dev == dev)
505 return bridge;
506
507 return NULL;
508}
509
510static struct prestera_bridge_port *
511__prestera_bridge_port_by_dev(struct prestera_bridge *bridge,
512 struct net_device *dev)
513{
514 struct prestera_bridge_port *br_port;
515
516 list_for_each_entry(br_port, &bridge->port_list, head) {
517 if (br_port->dev == dev)
518 return br_port;
519 }
520
521 return NULL;
522}
523
524static int prestera_match_upper_bridge_dev(struct net_device *dev,
525 struct netdev_nested_priv *priv)
526{
527 if (netif_is_bridge_master(dev))
528 priv->data = dev;
529
530 return 0;
531}
532
533static struct net_device *prestera_get_upper_bridge_dev(struct net_device *dev)
534{
535 struct netdev_nested_priv priv = { };
536
537 netdev_walk_all_upper_dev_rcu(dev, fn: prestera_match_upper_bridge_dev,
538 priv: &priv);
539 return priv.data;
540}
541
542static struct prestera_bridge_port *
543prestera_bridge_port_by_dev(struct prestera_switchdev *swdev,
544 struct net_device *dev)
545{
546 struct net_device *br_dev = prestera_get_upper_bridge_dev(dev);
547 struct prestera_bridge *bridge;
548
549 if (!br_dev)
550 return NULL;
551
552 bridge = prestera_bridge_by_dev(swdev, dev: br_dev);
553 if (!bridge)
554 return NULL;
555
556 return __prestera_bridge_port_by_dev(bridge, dev);
557}
558
559static struct prestera_bridge_port *
560prestera_bridge_port_create(struct prestera_bridge *bridge,
561 struct net_device *dev)
562{
563 struct prestera_bridge_port *br_port;
564
565 br_port = kzalloc(size: sizeof(*br_port), GFP_KERNEL);
566 if (!br_port)
567 return NULL;
568
569 br_port->flags = BR_LEARNING | BR_FLOOD | BR_LEARNING_SYNC |
570 BR_MCAST_FLOOD;
571 br_port->stp_state = BR_STATE_DISABLED;
572 refcount_set(r: &br_port->ref_count, n: 1);
573 br_port->bridge = bridge;
574 br_port->dev = dev;
575
576 INIT_LIST_HEAD(list: &br_port->vlan_list);
577 list_add(new: &br_port->head, head: &bridge->port_list);
578 INIT_LIST_HEAD(list: &br_port->br_mdb_port_list);
579
580 return br_port;
581}
582
583static void
584prestera_bridge_port_destroy(struct prestera_bridge_port *br_port)
585{
586 list_del(entry: &br_port->head);
587 WARN_ON(!list_empty(&br_port->vlan_list));
588 WARN_ON(!list_empty(&br_port->br_mdb_port_list));
589 kfree(objp: br_port);
590}
591
592static void prestera_bridge_port_get(struct prestera_bridge_port *br_port)
593{
594 refcount_inc(r: &br_port->ref_count);
595}
596
597static void prestera_bridge_port_put(struct prestera_bridge_port *br_port)
598{
599 struct prestera_bridge *bridge = br_port->bridge;
600
601 if (refcount_dec_and_test(r: &br_port->ref_count)) {
602 prestera_bridge_port_destroy(br_port);
603 prestera_bridge_put(bridge);
604 }
605}
606
607static struct prestera_bridge_port *
608prestera_bridge_port_add(struct prestera_bridge *bridge, struct net_device *dev)
609{
610 struct prestera_bridge_port *br_port;
611
612 br_port = __prestera_bridge_port_by_dev(bridge, dev);
613 if (br_port) {
614 prestera_bridge_port_get(br_port);
615 return br_port;
616 }
617
618 br_port = prestera_bridge_port_create(bridge, dev);
619 if (!br_port)
620 return ERR_PTR(error: -ENOMEM);
621
622 return br_port;
623}
624
625static int
626prestera_bridge_1d_port_join(struct prestera_bridge_port *br_port)
627{
628 struct prestera_port *port = netdev_priv(dev: br_port->dev);
629 struct prestera_bridge *bridge = br_port->bridge;
630 int err;
631
632 err = prestera_hw_bridge_port_add(port, bridge_id: bridge->bridge_id);
633 if (err)
634 return err;
635
636 err = prestera_br_port_flags_set(br_port, port);
637 if (err)
638 goto err_flags2port_set;
639
640 return 0;
641
642err_flags2port_set:
643 prestera_hw_bridge_port_delete(port, bridge_id: bridge->bridge_id);
644
645 return err;
646}
647
648int prestera_bridge_port_join(struct net_device *br_dev,
649 struct prestera_port *port,
650 struct netlink_ext_ack *extack)
651{
652 struct prestera_switchdev *swdev = port->sw->swdev;
653 struct prestera_bridge_port *br_port;
654 struct prestera_bridge *bridge;
655 int err;
656
657 bridge = prestera_bridge_by_dev(swdev, dev: br_dev);
658 if (!bridge) {
659 bridge = prestera_bridge_create(swdev, dev: br_dev);
660 if (IS_ERR(ptr: bridge))
661 return PTR_ERR(ptr: bridge);
662 }
663
664 br_port = prestera_bridge_port_add(bridge, dev: port->dev);
665 if (IS_ERR(ptr: br_port)) {
666 prestera_bridge_put(bridge);
667 return PTR_ERR(ptr: br_port);
668 }
669
670 err = switchdev_bridge_port_offload(brport_dev: br_port->dev, dev: port->dev, NULL,
671 NULL, NULL, tx_fwd_offload: false, extack);
672 if (err)
673 goto err_switchdev_offload;
674
675 if (bridge->vlan_enabled)
676 return 0;
677
678 err = prestera_bridge_1d_port_join(br_port);
679 if (err)
680 goto err_port_join;
681
682 return 0;
683
684err_port_join:
685 switchdev_bridge_port_unoffload(brport_dev: br_port->dev, NULL, NULL, NULL);
686err_switchdev_offload:
687 prestera_bridge_port_put(br_port);
688 return err;
689}
690
691static void prestera_bridge_1q_port_leave(struct prestera_bridge_port *br_port)
692{
693 struct prestera_port *port = netdev_priv(dev: br_port->dev);
694
695 prestera_hw_fdb_flush_port(port, mode: PRESTERA_FDB_FLUSH_MODE_ALL);
696 prestera_port_pvid_set(port, PRESTERA_DEFAULT_VID);
697}
698
699static void prestera_bridge_1d_port_leave(struct prestera_bridge_port *br_port)
700{
701 struct prestera_port *port = netdev_priv(dev: br_port->dev);
702
703 prestera_hw_fdb_flush_port(port, mode: PRESTERA_FDB_FLUSH_MODE_ALL);
704 prestera_hw_bridge_port_delete(port, bridge_id: br_port->bridge->bridge_id);
705}
706
707static int prestera_port_vid_stp_set(struct prestera_port *port, u16 vid,
708 u8 state)
709{
710 u8 hw_state = state;
711
712 switch (state) {
713 case BR_STATE_DISABLED:
714 hw_state = PRESTERA_STP_DISABLED;
715 break;
716
717 case BR_STATE_BLOCKING:
718 case BR_STATE_LISTENING:
719 hw_state = PRESTERA_STP_BLOCK_LISTEN;
720 break;
721
722 case BR_STATE_LEARNING:
723 hw_state = PRESTERA_STP_LEARN;
724 break;
725
726 case BR_STATE_FORWARDING:
727 hw_state = PRESTERA_STP_FORWARD;
728 break;
729
730 default:
731 return -EINVAL;
732 }
733
734 return prestera_hw_vlan_port_stp_set(port, vid, state: hw_state);
735}
736
737void prestera_bridge_port_leave(struct net_device *br_dev,
738 struct prestera_port *port)
739{
740 struct prestera_switchdev *swdev = port->sw->swdev;
741 struct prestera_bridge_port *br_port;
742 struct prestera_bridge *bridge;
743
744 bridge = prestera_bridge_by_dev(swdev, dev: br_dev);
745 if (!bridge)
746 return;
747
748 br_port = __prestera_bridge_port_by_dev(bridge, dev: port->dev);
749 if (!br_port)
750 return;
751
752 bridge = br_port->bridge;
753
754 if (bridge->vlan_enabled)
755 prestera_bridge_1q_port_leave(br_port);
756 else
757 prestera_bridge_1d_port_leave(br_port);
758
759 switchdev_bridge_port_unoffload(brport_dev: br_port->dev, NULL, NULL, NULL);
760
761 prestera_mdb_flush_bridge_port(br_port);
762
763 prestera_br_port_flags_reset(br_port, port);
764 prestera_port_vid_stp_set(port, PRESTERA_VID_ALL, BR_STATE_FORWARDING);
765 prestera_bridge_port_put(br_port);
766}
767
768static int prestera_port_attr_br_flags_set(struct prestera_port *port,
769 struct net_device *dev,
770 struct switchdev_brport_flags flags)
771{
772 struct prestera_bridge_port *br_port;
773
774 br_port = prestera_bridge_port_by_dev(swdev: port->sw->swdev, dev);
775 if (!br_port)
776 return 0;
777
778 br_port->flags &= ~flags.mask;
779 br_port->flags |= flags.val & flags.mask;
780 return prestera_br_port_flags_set(br_port, port);
781}
782
783static int prestera_port_attr_br_ageing_set(struct prestera_port *port,
784 unsigned long ageing_clock_t)
785{
786 unsigned long ageing_jiffies = clock_t_to_jiffies(x: ageing_clock_t);
787 u32 ageing_time_ms = jiffies_to_msecs(j: ageing_jiffies);
788 struct prestera_switch *sw = port->sw;
789
790 if (ageing_time_ms < PRESTERA_MIN_AGEING_TIME_MS ||
791 ageing_time_ms > PRESTERA_MAX_AGEING_TIME_MS)
792 return -ERANGE;
793
794 return prestera_hw_switch_ageing_set(sw, ageing_ms: ageing_time_ms);
795}
796
797static int prestera_port_attr_br_vlan_set(struct prestera_port *port,
798 struct net_device *dev,
799 bool vlan_enabled)
800{
801 struct prestera_switch *sw = port->sw;
802 struct prestera_bridge *bridge;
803
804 bridge = prestera_bridge_by_dev(swdev: sw->swdev, dev);
805 if (WARN_ON(!bridge))
806 return -EINVAL;
807
808 if (bridge->vlan_enabled == vlan_enabled)
809 return 0;
810
811 netdev_err(dev: bridge->dev, format: "VLAN filtering can't be changed for existing bridge\n");
812
813 return -EINVAL;
814}
815
816static int prestera_port_bridge_vlan_stp_set(struct prestera_port *port,
817 struct prestera_bridge_vlan *br_vlan,
818 u8 state)
819{
820 struct prestera_port_vlan *port_vlan;
821
822 list_for_each_entry(port_vlan, &br_vlan->port_vlan_list, br_vlan_head) {
823 if (port_vlan->port != port)
824 continue;
825
826 return prestera_port_vid_stp_set(port, vid: br_vlan->vid, state);
827 }
828
829 return 0;
830}
831
832static int prestera_port_attr_stp_state_set(struct prestera_port *port,
833 struct net_device *dev,
834 u8 state)
835{
836 struct prestera_bridge_port *br_port;
837 struct prestera_bridge_vlan *br_vlan;
838 int err;
839 u16 vid;
840
841 br_port = prestera_bridge_port_by_dev(swdev: port->sw->swdev, dev);
842 if (!br_port)
843 return 0;
844
845 if (!br_port->bridge->vlan_enabled) {
846 vid = br_port->bridge->bridge_id;
847 err = prestera_port_vid_stp_set(port, vid, state);
848 if (err)
849 goto err_port_stp_set;
850 } else {
851 list_for_each_entry(br_vlan, &br_port->vlan_list, head) {
852 err = prestera_port_bridge_vlan_stp_set(port, br_vlan,
853 state);
854 if (err)
855 goto err_port_vlan_stp_set;
856 }
857 }
858
859 br_port->stp_state = state;
860
861 return 0;
862
863err_port_vlan_stp_set:
864 list_for_each_entry_continue_reverse(br_vlan, &br_port->vlan_list, head)
865 prestera_port_bridge_vlan_stp_set(port, br_vlan, state: br_port->stp_state);
866 return err;
867
868err_port_stp_set:
869 prestera_port_vid_stp_set(port, vid, state: br_port->stp_state);
870
871 return err;
872}
873
874static int
875prestera_br_port_lag_mdb_mc_enable_sync(struct prestera_bridge_port *br_port,
876 bool enabled)
877{
878 struct prestera_port *pr_port;
879 struct prestera_switch *sw;
880 u16 lag_id;
881 int err;
882
883 pr_port = prestera_port_dev_lower_find(dev: br_port->dev);
884 if (!pr_port)
885 return 0;
886
887 sw = pr_port->sw;
888 err = prestera_lag_id(sw, lag_dev: br_port->dev, lag_id: &lag_id);
889 if (err)
890 return err;
891
892 list_for_each_entry(pr_port, &sw->port_list, list) {
893 if (pr_port->lag->lag_id == lag_id) {
894 err = prestera_port_mc_flood_set(port: pr_port, flood: enabled);
895 if (err)
896 return err;
897 }
898 }
899
900 return 0;
901}
902
903static int prestera_br_mdb_mc_enable_sync(struct prestera_bridge *br_dev)
904{
905 struct prestera_bridge_port *br_port;
906 struct prestera_port *port;
907 bool enabled;
908 int err;
909
910 /* if mrouter exists:
911 * - make sure every mrouter receives unreg mcast traffic;
912 * if mrouter doesn't exists:
913 * - make sure every port receives unreg mcast traffic;
914 */
915 list_for_each_entry(br_port, &br_dev->port_list, head) {
916 if (br_dev->multicast_enabled && br_dev->mrouter_exist)
917 enabled = br_port->mrouter;
918 else
919 enabled = br_port->flags & BR_MCAST_FLOOD;
920
921 if (netif_is_lag_master(dev: br_port->dev)) {
922 err = prestera_br_port_lag_mdb_mc_enable_sync(br_port,
923 enabled);
924 if (err)
925 return err;
926 continue;
927 }
928
929 port = prestera_port_dev_lower_find(dev: br_port->dev);
930 if (!port)
931 continue;
932
933 err = prestera_port_mc_flood_set(port, flood: enabled);
934 if (err)
935 return err;
936 }
937
938 return 0;
939}
940
941static bool
942prestera_br_mdb_port_is_member(struct prestera_br_mdb_entry *br_mdb,
943 struct net_device *orig_dev)
944{
945 struct prestera_br_mdb_port *tmp_port;
946
947 list_for_each_entry(tmp_port, &br_mdb->br_mdb_port_list,
948 br_mdb_port_node)
949 if (tmp_port->br_port->dev == orig_dev)
950 return true;
951
952 return false;
953}
954
955static int
956prestera_mdb_port_add(struct prestera_mdb_entry *mdb,
957 struct net_device *orig_dev,
958 const unsigned char addr[ETH_ALEN], u16 vid)
959{
960 struct prestera_flood_domain *flood_domain = mdb->flood_domain;
961 int err;
962
963 if (!prestera_flood_domain_port_find(flood_domain,
964 dev: orig_dev, vid)) {
965 err = prestera_flood_domain_port_create(flood_domain, dev: orig_dev,
966 vid);
967 if (err)
968 return err;
969 }
970
971 return 0;
972}
973
974/* Sync bridge mdb (software table) with HW table (if MC is enabled). */
975static int prestera_br_mdb_sync(struct prestera_bridge *br_dev)
976{
977 struct prestera_br_mdb_port *br_mdb_port;
978 struct prestera_bridge_port *br_port;
979 struct prestera_br_mdb_entry *br_mdb;
980 struct prestera_mdb_entry *mdb;
981 struct prestera_port *pr_port;
982 int err = 0;
983
984 if (!br_dev->multicast_enabled)
985 return 0;
986
987 list_for_each_entry(br_mdb, &br_dev->br_mdb_entry_list,
988 br_mdb_entry_node) {
989 mdb = br_mdb->mdb;
990 /* Make sure every port that explicitly been added to the mdb
991 * joins the specified group.
992 */
993 list_for_each_entry(br_mdb_port, &br_mdb->br_mdb_port_list,
994 br_mdb_port_node) {
995 br_port = br_mdb_port->br_port;
996 pr_port = prestera_port_dev_lower_find(dev: br_port->dev);
997
998 /* Match only mdb and br_mdb ports that belong to the
999 * same broadcast domain.
1000 */
1001 if (br_dev->vlan_enabled &&
1002 !prestera_port_vlan_by_vid(port: pr_port,
1003 vid: mdb->vid))
1004 continue;
1005
1006 /* If port is not in MDB or there's no Mrouter
1007 * clear HW mdb.
1008 */
1009 if (prestera_br_mdb_port_is_member(br_mdb,
1010 orig_dev: br_mdb_port->br_port->dev) &&
1011 br_dev->mrouter_exist)
1012 err = prestera_mdb_port_add(mdb, orig_dev: br_port->dev,
1013 addr: mdb->addr,
1014 vid: mdb->vid);
1015 else
1016 prestera_mdb_port_del(mdb, orig_dev: br_port->dev);
1017
1018 if (err)
1019 return err;
1020 }
1021
1022 /* Make sure that every mrouter port joins every MC group int
1023 * broadcast domain. If it's not an mrouter - it should leave
1024 */
1025 list_for_each_entry(br_port, &br_dev->port_list, head) {
1026 pr_port = prestera_port_dev_lower_find(dev: br_port->dev);
1027
1028 /* Make sure mrouter woudln't receive traffci from
1029 * another broadcast domain (e.g. from a vlan, which
1030 * mrouter port is not a member of).
1031 */
1032 if (br_dev->vlan_enabled &&
1033 !prestera_port_vlan_by_vid(port: pr_port,
1034 vid: mdb->vid))
1035 continue;
1036
1037 if (br_port->mrouter) {
1038 err = prestera_mdb_port_add(mdb, orig_dev: br_port->dev,
1039 addr: mdb->addr,
1040 vid: mdb->vid);
1041 if (err)
1042 return err;
1043 } else if (!br_port->mrouter &&
1044 !prestera_br_mdb_port_is_member
1045 (br_mdb, orig_dev: br_port->dev)) {
1046 prestera_mdb_port_del(mdb, orig_dev: br_port->dev);
1047 }
1048 }
1049 }
1050
1051 return 0;
1052}
1053
1054static int
1055prestera_mdb_enable_set(struct prestera_br_mdb_entry *br_mdb, bool enable)
1056{
1057 int err;
1058
1059 if (enable != br_mdb->enabled) {
1060 if (enable)
1061 err = prestera_hw_mdb_create(mdb: br_mdb->mdb);
1062 else
1063 err = prestera_hw_mdb_destroy(mdb: br_mdb->mdb);
1064
1065 if (err)
1066 return err;
1067
1068 br_mdb->enabled = enable;
1069 }
1070
1071 return 0;
1072}
1073
1074static int
1075prestera_br_mdb_enable_set(struct prestera_bridge *br_dev, bool enable)
1076{
1077 struct prestera_br_mdb_entry *br_mdb;
1078 int err;
1079
1080 list_for_each_entry(br_mdb, &br_dev->br_mdb_entry_list,
1081 br_mdb_entry_node) {
1082 err = prestera_mdb_enable_set(br_mdb, enable);
1083 if (err)
1084 return err;
1085 }
1086
1087 return 0;
1088}
1089
1090static int prestera_port_attr_br_mc_disabled_set(struct prestera_port *port,
1091 struct net_device *orig_dev,
1092 bool mc_disabled)
1093{
1094 struct prestera_switch *sw = port->sw;
1095 struct prestera_bridge *br_dev;
1096
1097 br_dev = prestera_bridge_find(sw, br_dev: orig_dev);
1098 if (!br_dev)
1099 return 0;
1100
1101 br_dev->multicast_enabled = !mc_disabled;
1102
1103 /* There's no point in enabling mdb back if router is missing. */
1104 WARN_ON(prestera_br_mdb_enable_set(br_dev, br_dev->multicast_enabled &&
1105 br_dev->mrouter_exist));
1106
1107 WARN_ON(prestera_br_mdb_sync(br_dev));
1108
1109 WARN_ON(prestera_br_mdb_mc_enable_sync(br_dev));
1110
1111 return 0;
1112}
1113
1114static bool
1115prestera_bridge_mdb_mc_mrouter_exists(struct prestera_bridge *br_dev)
1116{
1117 struct prestera_bridge_port *br_port;
1118
1119 list_for_each_entry(br_port, &br_dev->port_list, head)
1120 if (br_port->mrouter)
1121 return true;
1122
1123 return false;
1124}
1125
1126static int
1127prestera_port_attr_mrouter_set(struct prestera_port *port,
1128 struct net_device *orig_dev,
1129 bool is_port_mrouter)
1130{
1131 struct prestera_bridge_port *br_port;
1132 struct prestera_bridge *br_dev;
1133
1134 br_port = prestera_bridge_port_find(sw: port->sw, brport_dev: orig_dev);
1135 if (!br_port)
1136 return 0;
1137
1138 br_dev = br_port->bridge;
1139 br_port->mrouter = is_port_mrouter;
1140
1141 br_dev->mrouter_exist = prestera_bridge_mdb_mc_mrouter_exists(br_dev);
1142
1143 /* Enable MDB processing if both mrouter exists and mc is enabled.
1144 * In case if MC enabled, but there is no mrouter, device would flood
1145 * all multicast traffic (even if MDB table is not empty) with the use
1146 * of bridge's flood capabilities (without the use of flood_domain).
1147 */
1148 WARN_ON(prestera_br_mdb_enable_set(br_dev, br_dev->multicast_enabled &&
1149 br_dev->mrouter_exist));
1150
1151 WARN_ON(prestera_br_mdb_sync(br_dev));
1152
1153 WARN_ON(prestera_br_mdb_mc_enable_sync(br_dev));
1154
1155 return 0;
1156}
1157
1158static int prestera_port_obj_attr_set(struct net_device *dev, const void *ctx,
1159 const struct switchdev_attr *attr,
1160 struct netlink_ext_ack *extack)
1161{
1162 struct prestera_port *port = netdev_priv(dev);
1163 int err = 0;
1164
1165 switch (attr->id) {
1166 case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
1167 err = prestera_port_attr_stp_state_set(port, dev: attr->orig_dev,
1168 state: attr->u.stp_state);
1169 break;
1170 case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
1171 if (attr->u.brport_flags.mask &
1172 ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_PORT_LOCKED))
1173 err = -EINVAL;
1174 break;
1175 case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
1176 err = prestera_port_attr_br_flags_set(port, dev: attr->orig_dev,
1177 flags: attr->u.brport_flags);
1178 break;
1179 case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
1180 err = prestera_port_attr_br_ageing_set(port,
1181 ageing_clock_t: attr->u.ageing_time);
1182 break;
1183 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
1184 err = prestera_port_attr_br_vlan_set(port, dev: attr->orig_dev,
1185 vlan_enabled: attr->u.vlan_filtering);
1186 break;
1187 case SWITCHDEV_ATTR_ID_PORT_MROUTER:
1188 err = prestera_port_attr_mrouter_set(port, orig_dev: attr->orig_dev,
1189 is_port_mrouter: attr->u.mrouter);
1190 break;
1191 case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
1192 err = prestera_port_attr_br_mc_disabled_set(port, orig_dev: attr->orig_dev,
1193 mc_disabled: attr->u.mc_disabled);
1194 break;
1195 default:
1196 err = -EOPNOTSUPP;
1197 }
1198
1199 return err;
1200}
1201
1202static void
1203prestera_fdb_offload_notify(struct prestera_port *port,
1204 struct switchdev_notifier_fdb_info *info)
1205{
1206 struct switchdev_notifier_fdb_info send_info = {};
1207
1208 send_info.addr = info->addr;
1209 send_info.vid = info->vid;
1210 send_info.offloaded = true;
1211
1212 call_switchdev_notifiers(val: SWITCHDEV_FDB_OFFLOADED, dev: port->dev,
1213 info: &send_info.info, NULL);
1214}
1215
1216static int prestera_port_fdb_set(struct prestera_port *port,
1217 struct switchdev_notifier_fdb_info *fdb_info,
1218 bool adding)
1219{
1220 struct prestera_switch *sw = port->sw;
1221 struct prestera_bridge_port *br_port;
1222 struct prestera_bridge *bridge;
1223 int err;
1224 u16 vid;
1225
1226 br_port = prestera_bridge_port_by_dev(swdev: sw->swdev, dev: port->dev);
1227 if (!br_port)
1228 return -EINVAL;
1229
1230 bridge = br_port->bridge;
1231
1232 if (bridge->vlan_enabled)
1233 vid = fdb_info->vid;
1234 else
1235 vid = bridge->bridge_id;
1236
1237 if (adding)
1238 err = prestera_fdb_add(port, mac: fdb_info->addr, vid, dynamic: false);
1239 else
1240 err = prestera_fdb_del(port, mac: fdb_info->addr, vid);
1241
1242 return err;
1243}
1244
1245static void prestera_fdb_event_work(struct work_struct *work)
1246{
1247 struct switchdev_notifier_fdb_info *fdb_info;
1248 struct prestera_fdb_event_work *swdev_work;
1249 struct prestera_port *port;
1250 struct net_device *dev;
1251 int err;
1252
1253 swdev_work = container_of(work, struct prestera_fdb_event_work, work);
1254 dev = swdev_work->dev;
1255
1256 rtnl_lock();
1257
1258 port = prestera_port_dev_lower_find(dev);
1259 if (!port)
1260 goto out_unlock;
1261
1262 switch (swdev_work->event) {
1263 case SWITCHDEV_FDB_ADD_TO_DEVICE:
1264 fdb_info = &swdev_work->fdb_info;
1265 if (!fdb_info->added_by_user || fdb_info->is_local)
1266 break;
1267
1268 err = prestera_port_fdb_set(port, fdb_info, adding: true);
1269 if (err)
1270 break;
1271
1272 prestera_fdb_offload_notify(port, info: fdb_info);
1273 break;
1274
1275 case SWITCHDEV_FDB_DEL_TO_DEVICE:
1276 fdb_info = &swdev_work->fdb_info;
1277 prestera_port_fdb_set(port, fdb_info, adding: false);
1278 break;
1279 }
1280
1281out_unlock:
1282 rtnl_unlock();
1283
1284 kfree(objp: swdev_work->fdb_info.addr);
1285 kfree(objp: swdev_work);
1286 dev_put(dev);
1287}
1288
1289static int prestera_switchdev_event(struct notifier_block *unused,
1290 unsigned long event, void *ptr)
1291{
1292 struct net_device *dev = switchdev_notifier_info_to_dev(info: ptr);
1293 struct switchdev_notifier_fdb_info *fdb_info;
1294 struct switchdev_notifier_info *info = ptr;
1295 struct prestera_fdb_event_work *swdev_work;
1296 struct net_device *upper;
1297 int err;
1298
1299 if (event == SWITCHDEV_PORT_ATTR_SET) {
1300 err = switchdev_handle_port_attr_set(dev, port_attr_info: ptr,
1301 check_cb: prestera_netdev_check,
1302 set_cb: prestera_port_obj_attr_set);
1303 return notifier_from_errno(err);
1304 }
1305
1306 if (!prestera_netdev_check(dev))
1307 return NOTIFY_DONE;
1308
1309 upper = netdev_master_upper_dev_get_rcu(dev);
1310 if (!upper)
1311 return NOTIFY_DONE;
1312
1313 if (!netif_is_bridge_master(dev: upper))
1314 return NOTIFY_DONE;
1315
1316 swdev_work = kzalloc(size: sizeof(*swdev_work), GFP_ATOMIC);
1317 if (!swdev_work)
1318 return NOTIFY_BAD;
1319
1320 swdev_work->event = event;
1321 swdev_work->dev = dev;
1322
1323 switch (event) {
1324 case SWITCHDEV_FDB_ADD_TO_DEVICE:
1325 case SWITCHDEV_FDB_DEL_TO_DEVICE:
1326 fdb_info = container_of(info,
1327 struct switchdev_notifier_fdb_info,
1328 info);
1329
1330 INIT_WORK(&swdev_work->work, prestera_fdb_event_work);
1331 memcpy(&swdev_work->fdb_info, ptr,
1332 sizeof(swdev_work->fdb_info));
1333
1334 swdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
1335 if (!swdev_work->fdb_info.addr)
1336 goto out_bad;
1337
1338 ether_addr_copy(dst: (u8 *)swdev_work->fdb_info.addr,
1339 src: fdb_info->addr);
1340 dev_hold(dev);
1341 break;
1342
1343 default:
1344 kfree(objp: swdev_work);
1345 return NOTIFY_DONE;
1346 }
1347
1348 queue_work(wq: swdev_wq, work: &swdev_work->work);
1349 return NOTIFY_DONE;
1350
1351out_bad:
1352 kfree(objp: swdev_work);
1353 return NOTIFY_BAD;
1354}
1355
1356static int
1357prestera_port_vlan_bridge_join(struct prestera_port_vlan *port_vlan,
1358 struct prestera_bridge_port *br_port)
1359{
1360 struct prestera_port *port = port_vlan->port;
1361 struct prestera_bridge_vlan *br_vlan;
1362 u16 vid = port_vlan->vid;
1363 int err;
1364
1365 if (port_vlan->br_port)
1366 return 0;
1367
1368 err = prestera_br_port_flags_set(br_port, port);
1369 if (err)
1370 goto err_flags2port_set;
1371
1372 err = prestera_port_vid_stp_set(port, vid, state: br_port->stp_state);
1373 if (err)
1374 goto err_port_vid_stp_set;
1375
1376 br_vlan = prestera_bridge_vlan_by_vid(br_port, vid);
1377 if (!br_vlan) {
1378 br_vlan = prestera_bridge_vlan_create(br_port, vid);
1379 if (!br_vlan) {
1380 err = -ENOMEM;
1381 goto err_bridge_vlan_get;
1382 }
1383 }
1384
1385 list_add(new: &port_vlan->br_vlan_head, head: &br_vlan->port_vlan_list);
1386
1387 prestera_bridge_port_get(br_port);
1388 port_vlan->br_port = br_port;
1389
1390 return 0;
1391
1392err_bridge_vlan_get:
1393 prestera_port_vid_stp_set(port, vid, BR_STATE_FORWARDING);
1394err_port_vid_stp_set:
1395 prestera_br_port_flags_reset(br_port, port);
1396err_flags2port_set:
1397 return err;
1398}
1399
1400static int
1401prestera_bridge_port_vlan_add(struct prestera_port *port,
1402 struct prestera_bridge_port *br_port,
1403 u16 vid, bool is_untagged, bool is_pvid,
1404 struct netlink_ext_ack *extack)
1405{
1406 struct prestera_port_vlan *port_vlan;
1407 u16 old_pvid = port->pvid;
1408 u16 pvid;
1409 int err;
1410
1411 if (is_pvid)
1412 pvid = vid;
1413 else
1414 pvid = port->pvid == vid ? 0 : port->pvid;
1415
1416 port_vlan = prestera_port_vlan_by_vid(port, vid);
1417 if (port_vlan && port_vlan->br_port != br_port)
1418 return -EEXIST;
1419
1420 if (!port_vlan) {
1421 port_vlan = prestera_port_vlan_create(port, vid, untagged: is_untagged);
1422 if (IS_ERR(ptr: port_vlan))
1423 return PTR_ERR(ptr: port_vlan);
1424 } else {
1425 err = prestera_hw_vlan_port_set(port, vid, is_member: true, untagged: is_untagged);
1426 if (err)
1427 goto err_port_vlan_set;
1428 }
1429
1430 err = prestera_port_pvid_set(port, vid: pvid);
1431 if (err)
1432 goto err_port_pvid_set;
1433
1434 err = prestera_port_vlan_bridge_join(port_vlan, br_port);
1435 if (err)
1436 goto err_port_vlan_bridge_join;
1437
1438 return 0;
1439
1440err_port_vlan_bridge_join:
1441 prestera_port_pvid_set(port, vid: old_pvid);
1442err_port_pvid_set:
1443 prestera_hw_vlan_port_set(port, vid, is_member: false, untagged: false);
1444err_port_vlan_set:
1445 prestera_port_vlan_destroy(port_vlan);
1446
1447 return err;
1448}
1449
1450static void
1451prestera_bridge_port_vlan_del(struct prestera_port *port,
1452 struct prestera_bridge_port *br_port, u16 vid)
1453{
1454 u16 pvid = port->pvid == vid ? 0 : port->pvid;
1455 struct prestera_port_vlan *port_vlan;
1456
1457 port_vlan = prestera_port_vlan_by_vid(port, vid);
1458 if (WARN_ON(!port_vlan))
1459 return;
1460
1461 prestera_port_vlan_bridge_leave(port_vlan);
1462 prestera_port_pvid_set(port, vid: pvid);
1463 prestera_port_vlan_destroy(port_vlan);
1464}
1465
1466static int prestera_port_vlans_add(struct prestera_port *port,
1467 const struct switchdev_obj_port_vlan *vlan,
1468 struct netlink_ext_ack *extack)
1469{
1470 bool flag_untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
1471 bool flag_pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
1472 struct net_device *orig_dev = vlan->obj.orig_dev;
1473 struct prestera_bridge_port *br_port;
1474 struct prestera_switch *sw = port->sw;
1475 struct prestera_bridge *bridge;
1476
1477 if (netif_is_bridge_master(dev: orig_dev))
1478 return 0;
1479
1480 br_port = prestera_bridge_port_by_dev(swdev: sw->swdev, dev: port->dev);
1481 if (WARN_ON(!br_port))
1482 return -EINVAL;
1483
1484 bridge = br_port->bridge;
1485 if (!bridge->vlan_enabled)
1486 return 0;
1487
1488 return prestera_bridge_port_vlan_add(port, br_port,
1489 vid: vlan->vid, is_untagged: flag_untagged,
1490 is_pvid: flag_pvid, extack);
1491}
1492
1493static struct prestera_br_mdb_entry *
1494prestera_br_mdb_entry_create(struct prestera_switch *sw,
1495 struct prestera_bridge *br_dev,
1496 const unsigned char *addr, u16 vid)
1497{
1498 struct prestera_br_mdb_entry *br_mdb_entry;
1499 struct prestera_mdb_entry *mdb_entry;
1500
1501 br_mdb_entry = kzalloc(size: sizeof(*br_mdb_entry), GFP_KERNEL);
1502 if (!br_mdb_entry)
1503 return NULL;
1504
1505 mdb_entry = prestera_mdb_entry_create(sw, addr, vid);
1506 if (!mdb_entry)
1507 goto err_mdb_alloc;
1508
1509 br_mdb_entry->mdb = mdb_entry;
1510 br_mdb_entry->bridge = br_dev;
1511 br_mdb_entry->enabled = true;
1512 INIT_LIST_HEAD(list: &br_mdb_entry->br_mdb_port_list);
1513
1514 list_add(new: &br_mdb_entry->br_mdb_entry_node, head: &br_dev->br_mdb_entry_list);
1515
1516 return br_mdb_entry;
1517
1518err_mdb_alloc:
1519 kfree(objp: br_mdb_entry);
1520 return NULL;
1521}
1522
1523static int prestera_br_mdb_port_add(struct prestera_br_mdb_entry *br_mdb,
1524 struct prestera_bridge_port *br_port)
1525{
1526 struct prestera_br_mdb_port *br_mdb_port;
1527
1528 list_for_each_entry(br_mdb_port, &br_mdb->br_mdb_port_list,
1529 br_mdb_port_node)
1530 if (br_mdb_port->br_port == br_port)
1531 return 0;
1532
1533 br_mdb_port = kzalloc(size: sizeof(*br_mdb_port), GFP_KERNEL);
1534 if (!br_mdb_port)
1535 return -ENOMEM;
1536
1537 br_mdb_port->br_port = br_port;
1538 list_add(new: &br_mdb_port->br_mdb_port_node,
1539 head: &br_mdb->br_mdb_port_list);
1540
1541 return 0;
1542}
1543
1544static struct prestera_br_mdb_entry *
1545prestera_br_mdb_entry_find(struct prestera_bridge *br_dev,
1546 const unsigned char *addr, u16 vid)
1547{
1548 struct prestera_br_mdb_entry *br_mdb;
1549
1550 list_for_each_entry(br_mdb, &br_dev->br_mdb_entry_list,
1551 br_mdb_entry_node)
1552 if (ether_addr_equal(addr1: &br_mdb->mdb->addr[0], addr2: addr) &&
1553 vid == br_mdb->mdb->vid)
1554 return br_mdb;
1555
1556 return NULL;
1557}
1558
1559static struct prestera_br_mdb_entry *
1560prestera_br_mdb_entry_get(struct prestera_switch *sw,
1561 struct prestera_bridge *br_dev,
1562 const unsigned char *addr, u16 vid)
1563{
1564 struct prestera_br_mdb_entry *br_mdb;
1565
1566 br_mdb = prestera_br_mdb_entry_find(br_dev, addr, vid);
1567 if (br_mdb)
1568 return br_mdb;
1569
1570 return prestera_br_mdb_entry_create(sw, br_dev, addr, vid);
1571}
1572
1573static int
1574prestera_mdb_port_addr_obj_add(const struct switchdev_obj_port_mdb *mdb)
1575{
1576 struct prestera_br_mdb_entry *br_mdb;
1577 struct prestera_bridge_port *br_port;
1578 struct prestera_bridge *br_dev;
1579 struct prestera_switch *sw;
1580 struct prestera_port *port;
1581 int err;
1582
1583 sw = prestera_switch_get(dev: mdb->obj.orig_dev);
1584 port = prestera_port_dev_lower_find(dev: mdb->obj.orig_dev);
1585
1586 br_port = prestera_bridge_port_find(sw, brport_dev: mdb->obj.orig_dev);
1587 if (!br_port)
1588 return 0;
1589
1590 br_dev = br_port->bridge;
1591
1592 if (mdb->vid && !prestera_port_vlan_by_vid(port, vid: mdb->vid))
1593 return 0;
1594
1595 if (mdb->vid)
1596 br_mdb = prestera_br_mdb_entry_get(sw, br_dev, addr: &mdb->addr[0],
1597 vid: mdb->vid);
1598 else
1599 br_mdb = prestera_br_mdb_entry_get(sw, br_dev, addr: &mdb->addr[0],
1600 vid: br_dev->bridge_id);
1601
1602 if (!br_mdb)
1603 return -ENOMEM;
1604
1605 /* Make sure newly allocated MDB entry gets disabled if either MC is
1606 * disabled, or the mrouter does not exist.
1607 */
1608 WARN_ON(prestera_mdb_enable_set(br_mdb, br_dev->multicast_enabled &&
1609 br_dev->mrouter_exist));
1610
1611 err = prestera_br_mdb_port_add(br_mdb, br_port);
1612 if (err) {
1613 prestera_br_mdb_entry_put(br_mdb);
1614 return err;
1615 }
1616
1617 err = prestera_br_mdb_sync(br_dev);
1618 if (err)
1619 return err;
1620
1621 return 0;
1622}
1623
1624static int prestera_port_obj_add(struct net_device *dev, const void *ctx,
1625 const struct switchdev_obj *obj,
1626 struct netlink_ext_ack *extack)
1627{
1628 struct prestera_port *port = netdev_priv(dev);
1629 const struct switchdev_obj_port_vlan *vlan;
1630 const struct switchdev_obj_port_mdb *mdb;
1631 int err = 0;
1632
1633 switch (obj->id) {
1634 case SWITCHDEV_OBJ_ID_PORT_VLAN:
1635 vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
1636 return prestera_port_vlans_add(port, vlan, extack);
1637 case SWITCHDEV_OBJ_ID_PORT_MDB:
1638 mdb = SWITCHDEV_OBJ_PORT_MDB(obj);
1639 err = prestera_mdb_port_addr_obj_add(mdb);
1640 break;
1641 case SWITCHDEV_OBJ_ID_HOST_MDB:
1642 fallthrough;
1643 default:
1644 err = -EOPNOTSUPP;
1645 break;
1646 }
1647
1648 return err;
1649}
1650
1651static int prestera_port_vlans_del(struct prestera_port *port,
1652 const struct switchdev_obj_port_vlan *vlan)
1653{
1654 struct net_device *orig_dev = vlan->obj.orig_dev;
1655 struct prestera_bridge_port *br_port;
1656 struct prestera_switch *sw = port->sw;
1657
1658 if (netif_is_bridge_master(dev: orig_dev))
1659 return -EOPNOTSUPP;
1660
1661 br_port = prestera_bridge_port_by_dev(swdev: sw->swdev, dev: port->dev);
1662 if (WARN_ON(!br_port))
1663 return -EINVAL;
1664
1665 if (!br_port->bridge->vlan_enabled)
1666 return 0;
1667
1668 prestera_bridge_port_vlan_del(port, br_port, vid: vlan->vid);
1669
1670 return 0;
1671}
1672
1673static int
1674prestera_mdb_port_addr_obj_del(struct prestera_port *port,
1675 const struct switchdev_obj_port_mdb *mdb)
1676{
1677 struct prestera_br_mdb_entry *br_mdb;
1678 struct prestera_bridge_port *br_port;
1679 struct prestera_bridge *br_dev;
1680 int err;
1681
1682 /* Bridge port no longer exists - and so does this MDB entry */
1683 br_port = prestera_bridge_port_find(sw: port->sw, brport_dev: mdb->obj.orig_dev);
1684 if (!br_port)
1685 return 0;
1686
1687 /* Removing MDB with non-existing VLAN - not supported; */
1688 if (mdb->vid && !prestera_port_vlan_by_vid(port, vid: mdb->vid))
1689 return 0;
1690
1691 br_dev = br_port->bridge;
1692
1693 if (br_port->bridge->vlan_enabled)
1694 br_mdb = prestera_br_mdb_entry_find(br_dev, addr: &mdb->addr[0],
1695 vid: mdb->vid);
1696 else
1697 br_mdb = prestera_br_mdb_entry_find(br_dev, addr: &mdb->addr[0],
1698 vid: br_port->bridge->bridge_id);
1699
1700 if (!br_mdb)
1701 return 0;
1702
1703 /* Since there might be a situation that this port was the last in the
1704 * MDB group, we have to both remove this port from software and HW MDB,
1705 * sync MDB table, and then destroy software MDB (if needed).
1706 */
1707 prestera_br_mdb_port_del(br_mdb, br_port);
1708
1709 prestera_br_mdb_entry_put(br_mdb);
1710
1711 err = prestera_br_mdb_sync(br_dev);
1712 if (err)
1713 return err;
1714
1715 return 0;
1716}
1717
1718static int prestera_port_obj_del(struct net_device *dev, const void *ctx,
1719 const struct switchdev_obj *obj)
1720{
1721 struct prestera_port *port = netdev_priv(dev);
1722 const struct switchdev_obj_port_mdb *mdb;
1723 int err = 0;
1724
1725 switch (obj->id) {
1726 case SWITCHDEV_OBJ_ID_PORT_VLAN:
1727 return prestera_port_vlans_del(port, SWITCHDEV_OBJ_PORT_VLAN(obj));
1728 case SWITCHDEV_OBJ_ID_PORT_MDB:
1729 mdb = SWITCHDEV_OBJ_PORT_MDB(obj);
1730 err = prestera_mdb_port_addr_obj_del(port, mdb);
1731 break;
1732 default:
1733 err = -EOPNOTSUPP;
1734 break;
1735 }
1736
1737 return err;
1738}
1739
1740static int prestera_switchdev_blk_event(struct notifier_block *unused,
1741 unsigned long event, void *ptr)
1742{
1743 struct net_device *dev = switchdev_notifier_info_to_dev(info: ptr);
1744 int err;
1745
1746 switch (event) {
1747 case SWITCHDEV_PORT_OBJ_ADD:
1748 err = switchdev_handle_port_obj_add(dev, port_obj_info: ptr,
1749 check_cb: prestera_netdev_check,
1750 add_cb: prestera_port_obj_add);
1751 break;
1752 case SWITCHDEV_PORT_OBJ_DEL:
1753 err = switchdev_handle_port_obj_del(dev, port_obj_info: ptr,
1754 check_cb: prestera_netdev_check,
1755 del_cb: prestera_port_obj_del);
1756 break;
1757 case SWITCHDEV_PORT_ATTR_SET:
1758 err = switchdev_handle_port_attr_set(dev, port_attr_info: ptr,
1759 check_cb: prestera_netdev_check,
1760 set_cb: prestera_port_obj_attr_set);
1761 break;
1762 default:
1763 return NOTIFY_DONE;
1764 }
1765
1766 return notifier_from_errno(err);
1767}
1768
1769static void prestera_fdb_event(struct prestera_switch *sw,
1770 struct prestera_event *evt, void *arg)
1771{
1772 struct switchdev_notifier_fdb_info info = {};
1773 struct net_device *dev = NULL;
1774 struct prestera_port *port;
1775 struct prestera_lag *lag;
1776
1777 switch (evt->fdb_evt.type) {
1778 case PRESTERA_FDB_ENTRY_TYPE_REG_PORT:
1779 port = prestera_find_port(sw, id: evt->fdb_evt.dest.port_id);
1780 if (port)
1781 dev = port->dev;
1782 break;
1783 case PRESTERA_FDB_ENTRY_TYPE_LAG:
1784 lag = prestera_lag_by_id(sw, id: evt->fdb_evt.dest.lag_id);
1785 if (lag)
1786 dev = lag->dev;
1787 break;
1788 default:
1789 return;
1790 }
1791
1792 if (!dev)
1793 return;
1794
1795 info.addr = evt->fdb_evt.data.mac;
1796 info.vid = evt->fdb_evt.vid;
1797 info.offloaded = true;
1798
1799 rtnl_lock();
1800
1801 switch (evt->id) {
1802 case PRESTERA_FDB_EVENT_LEARNED:
1803 call_switchdev_notifiers(val: SWITCHDEV_FDB_ADD_TO_BRIDGE,
1804 dev, info: &info.info, NULL);
1805 break;
1806 case PRESTERA_FDB_EVENT_AGED:
1807 call_switchdev_notifiers(val: SWITCHDEV_FDB_DEL_TO_BRIDGE,
1808 dev, info: &info.info, NULL);
1809 break;
1810 }
1811
1812 rtnl_unlock();
1813}
1814
1815static int prestera_fdb_init(struct prestera_switch *sw)
1816{
1817 int err;
1818
1819 err = prestera_hw_event_handler_register(sw, type: PRESTERA_EVENT_TYPE_FDB,
1820 fn: prestera_fdb_event, NULL);
1821 if (err)
1822 return err;
1823
1824 err = prestera_hw_switch_ageing_set(sw, PRESTERA_DEFAULT_AGEING_TIME_MS);
1825 if (err)
1826 goto err_ageing_set;
1827
1828 return 0;
1829
1830err_ageing_set:
1831 prestera_hw_event_handler_unregister(sw, type: PRESTERA_EVENT_TYPE_FDB,
1832 fn: prestera_fdb_event);
1833 return err;
1834}
1835
1836static void prestera_fdb_fini(struct prestera_switch *sw)
1837{
1838 prestera_hw_event_handler_unregister(sw, type: PRESTERA_EVENT_TYPE_FDB,
1839 fn: prestera_fdb_event);
1840}
1841
1842static int prestera_switchdev_handler_init(struct prestera_switchdev *swdev)
1843{
1844 int err;
1845
1846 swdev->swdev_nb.notifier_call = prestera_switchdev_event;
1847 err = register_switchdev_notifier(nb: &swdev->swdev_nb);
1848 if (err)
1849 goto err_register_swdev_notifier;
1850
1851 swdev->swdev_nb_blk.notifier_call = prestera_switchdev_blk_event;
1852 err = register_switchdev_blocking_notifier(nb: &swdev->swdev_nb_blk);
1853 if (err)
1854 goto err_register_blk_swdev_notifier;
1855
1856 return 0;
1857
1858err_register_blk_swdev_notifier:
1859 unregister_switchdev_notifier(nb: &swdev->swdev_nb);
1860err_register_swdev_notifier:
1861 destroy_workqueue(wq: swdev_wq);
1862 return err;
1863}
1864
1865static void prestera_switchdev_handler_fini(struct prestera_switchdev *swdev)
1866{
1867 unregister_switchdev_blocking_notifier(nb: &swdev->swdev_nb_blk);
1868 unregister_switchdev_notifier(nb: &swdev->swdev_nb);
1869}
1870
1871int prestera_switchdev_init(struct prestera_switch *sw)
1872{
1873 struct prestera_switchdev *swdev;
1874 int err;
1875
1876 swdev = kzalloc(size: sizeof(*swdev), GFP_KERNEL);
1877 if (!swdev)
1878 return -ENOMEM;
1879
1880 sw->swdev = swdev;
1881 swdev->sw = sw;
1882
1883 INIT_LIST_HEAD(list: &swdev->bridge_list);
1884
1885 swdev_wq = alloc_ordered_workqueue("%s_ordered", 0, "prestera_br");
1886 if (!swdev_wq) {
1887 err = -ENOMEM;
1888 goto err_alloc_wq;
1889 }
1890
1891 err = prestera_switchdev_handler_init(swdev);
1892 if (err)
1893 goto err_swdev_init;
1894
1895 err = prestera_fdb_init(sw);
1896 if (err)
1897 goto err_fdb_init;
1898
1899 return 0;
1900
1901err_fdb_init:
1902err_swdev_init:
1903 destroy_workqueue(wq: swdev_wq);
1904err_alloc_wq:
1905 kfree(objp: swdev);
1906
1907 return err;
1908}
1909
1910void prestera_switchdev_fini(struct prestera_switch *sw)
1911{
1912 struct prestera_switchdev *swdev = sw->swdev;
1913
1914 prestera_fdb_fini(sw);
1915 prestera_switchdev_handler_fini(swdev);
1916 destroy_workqueue(wq: swdev_wq);
1917 kfree(objp: swdev);
1918}
1919

source code of linux/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c