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, cb: __mv88e6xxx_find_vid, priv: &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: &vid); |
66 | if (err) |
67 | return err; |
68 | |
69 | info.vid = vid; |
70 | dp = dsa_to_port(ds: chip->ds, p: 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(val: SWITCHDEV_FDB_ADD_TO_BRIDGE, |
79 | dev: brport, info: &info.info, NULL); |
80 | rtnl_unlock(); |
81 | |
82 | return err; |
83 | } |
84 | |