]> Git Repo - linux.git/blob - drivers/net/dsa/mv88e6xxx/switchdev.c
Linux 6.14-rc3
[linux.git] / drivers / net / dsa / mv88e6xxx / switchdev.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * switchdev.c
4  *
5  *      Authors:
6  *      Hans J. Schultz         <[email protected]>
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 }
This page took 0.03698 seconds and 4 git commands to generate.