Commit | Line | Data |
---|---|---|
830763b9 HS |
1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* | |
3 | * switchdev.c | |
4 | * | |
5 | * Authors: | |
6 | * Hans J. Schultz <netdev@kapio-technology.com> | |
7 | * | |
8 | */ | |
9 | ||
10 | #include <net/switchdev.h> | |
11 | #include "chip.h" | |
12 | #include "global1.h" | |
13 | #include "switchdev.h" | |
14 | ||
15 | struct mv88e6xxx_fid_search_ctx { | |
16 | u16 fid_search; | |
17 | u16 vid_found; | |
18 | }; | |
19 | ||
20 | static int __mv88e6xxx_find_vid(struct mv88e6xxx_chip *chip, | |
21 | const struct mv88e6xxx_vtu_entry *entry, | |
22 | void *priv) | |
23 | { | |
24 | struct mv88e6xxx_fid_search_ctx *ctx = priv; | |
25 | ||
26 | if (ctx->fid_search == entry->fid) { | |
27 | ctx->vid_found = entry->vid; | |
28 | return 1; | |
29 | } | |
30 | ||
31 | return 0; | |
32 | } | |
33 | ||
34 | static int mv88e6xxx_find_vid(struct mv88e6xxx_chip *chip, u16 fid, u16 *vid) | |
35 | { | |
36 | struct mv88e6xxx_fid_search_ctx ctx; | |
37 | int err; | |
38 | ||
39 | ctx.fid_search = fid; | |
40 | mv88e6xxx_reg_lock(chip); | |
41 | err = mv88e6xxx_vtu_walk(chip, __mv88e6xxx_find_vid, &ctx); | |
42 | mv88e6xxx_reg_unlock(chip); | |
43 | if (err < 0) | |
44 | return err; | |
45 | if (err == 1) | |
46 | *vid = ctx.vid_found; | |
47 | else | |
48 | return -ENOENT; | |
49 | ||
50 | return 0; | |
51 | } | |
52 | ||
53 | int mv88e6xxx_handle_miss_violation(struct mv88e6xxx_chip *chip, int port, | |
54 | struct mv88e6xxx_atu_entry *entry, u16 fid) | |
55 | { | |
56 | struct switchdev_notifier_fdb_info info = { | |
57 | .addr = entry->mac, | |
58 | .locked = true, | |
59 | }; | |
60 | struct net_device *brport; | |
61 | struct dsa_port *dp; | |
62 | u16 vid; | |
63 | int err; | |
64 | ||
65 | err = mv88e6xxx_find_vid(chip, fid, &vid); | |
66 | if (err) | |
67 | return err; | |
68 | ||
69 | info.vid = vid; | |
70 | dp = dsa_to_port(chip->ds, port); | |
71 | ||
72 | rtnl_lock(); | |
73 | brport = dsa_port_to_bridge_port(dp); | |
74 | if (!brport) { | |
75 | rtnl_unlock(); | |
76 | return -ENODEV; | |
77 | } | |
78 | err = call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE, | |
79 | brport, &info.info, NULL); | |
80 | rtnl_unlock(); | |
81 | ||
82 | return err; | |
83 | } |