// SPDX-License-Identifier: GPL-2.0-or-later /* * switchdev.c * * Authors: * Hans J. Schultz * */ #include #include "chip.h" #include "global1.h" #include "switchdev.h" struct mv88e6xxx_fid_search_ctx { u16 fid_search; u16 vid_found; }; static int __mv88e6xxx_find_vid(struct mv88e6xxx_chip *chip, const struct mv88e6xxx_vtu_entry *entry, void *priv) { struct mv88e6xxx_fid_search_ctx *ctx = priv; if (ctx->fid_search == entry->fid) { ctx->vid_found = entry->vid; return 1; } return 0; } static int mv88e6xxx_find_vid(struct mv88e6xxx_chip *chip, u16 fid, u16 *vid) { struct mv88e6xxx_fid_search_ctx ctx; int err; ctx.fid_search = fid; mv88e6xxx_reg_lock(chip); err = mv88e6xxx_vtu_walk(chip, __mv88e6xxx_find_vid, &ctx); mv88e6xxx_reg_unlock(chip); if (err < 0) return err; if (err == 1) *vid = ctx.vid_found; else return -ENOENT; return 0; } int mv88e6xxx_handle_miss_violation(struct mv88e6xxx_chip *chip, int port, struct mv88e6xxx_atu_entry *entry, u16 fid) { struct switchdev_notifier_fdb_info info = { .addr = entry->mac, .locked = true, }; struct net_device *brport; struct dsa_port *dp; u16 vid; int err; err = mv88e6xxx_find_vid(chip, fid, &vid); if (err) return err; info.vid = vid; dp = dsa_to_port(chip->ds, port); rtnl_lock(); brport = dsa_port_to_bridge_port(dp); if (!brport) { rtnl_unlock(); return -ENODEV; } err = call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE, brport, &info.info, NULL); rtnl_unlock(); return err; }