84 lines
1.6 KiB
C
84 lines
1.6 KiB
C
|
// 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;
|
||
|
}
|