xref: /linux/drivers/net/dsa/mv88e6xxx/switchdev.c (revision 8e07e0e3964ca4e23ce7b68e2096fe660a888942)
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 }
84