1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* switchdev.c
*
* Authors:
* Hans J. Schultz <netdev@kapio-technology.com>
*
*/
#include <net/switchdev.h>
#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;
}
|