Commit a3ae1603 authored by Paolo Abeni's avatar Paolo Abeni

Merge branch 'mv88e6xxx-add-mab-offload-support'

Hans J. Schultz says:

====================
mv88e6xxx: Add MAB offload support

This patch-set adds MAB [1] offload support in mv88e6xxx.

Patch #1: Correct default return value for mv88e6xxx_port_bridge_flags.

Patch #2: Shorten the locked section in
          mv88e6xxx_g1_atu_prob_irq_thread_fn().

Patch #3: The MAB implementation for mv88e6xxx.

[1] https://git.kernel.org/netdev/net-next/c/4bf24ad09bc0
====================

Link: https://lore.kernel.org/r/20230108094849.1789162-1-netdev@kapio-technology.comSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 07445f3c 830763b9
......@@ -15,6 +15,7 @@ mv88e6xxx-objs += port_hidden.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += ptp.o
mv88e6xxx-objs += serdes.o
mv88e6xxx-objs += smi.o
mv88e6xxx-objs += switchdev.o
mv88e6xxx-objs += trace.o
# for tracing framework to find trace.h
......
......@@ -1728,11 +1728,11 @@ static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
return err;
}
static int mv88e6xxx_vtu_walk(struct mv88e6xxx_chip *chip,
int (*cb)(struct mv88e6xxx_chip *chip,
const struct mv88e6xxx_vtu_entry *entry,
void *priv),
void *priv)
int mv88e6xxx_vtu_walk(struct mv88e6xxx_chip *chip,
int (*cb)(struct mv88e6xxx_chip *chip,
const struct mv88e6xxx_vtu_entry *entry,
void *priv),
void *priv)
{
struct mv88e6xxx_vtu_entry entry = {
.vid = mv88e6xxx_max_vid(chip),
......@@ -6526,7 +6526,7 @@ static int mv88e6xxx_port_pre_bridge_flags(struct dsa_switch *ds, int port,
const struct mv88e6xxx_ops *ops;
if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD |
BR_BCAST_FLOOD | BR_PORT_LOCKED))
BR_BCAST_FLOOD | BR_PORT_LOCKED | BR_PORT_MAB))
return -EINVAL;
ops = chip->info->ops;
......@@ -6545,7 +6545,7 @@ static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port,
struct netlink_ext_ack *extack)
{
struct mv88e6xxx_chip *chip = ds->priv;
int err = -EOPNOTSUPP;
int err = 0;
mv88e6xxx_reg_lock(chip);
......@@ -6584,6 +6584,12 @@ static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port,
goto out;
}
if (flags.mask & BR_PORT_MAB) {
bool mab = !!(flags.val & BR_PORT_MAB);
mv88e6xxx_port_set_mab(chip, port, mab);
}
if (flags.mask & BR_PORT_LOCKED) {
bool locked = !!(flags.val & BR_PORT_LOCKED);
......
......@@ -280,6 +280,9 @@ struct mv88e6xxx_port {
unsigned int serdes_irq;
char serdes_irq_name[64];
struct devlink_region *region;
/* MacAuth Bypass control flag */
bool mab;
};
enum mv88e6xxx_region_id {
......@@ -784,6 +787,12 @@ static inline bool mv88e6xxx_is_invalid_port(struct mv88e6xxx_chip *chip, int po
return (chip->info->invalid_port_mask & BIT(port)) != 0;
}
static inline void mv88e6xxx_port_set_mab(struct mv88e6xxx_chip *chip,
int port, bool mab)
{
chip->ports[port].mab = mab;
}
int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
......@@ -802,6 +811,12 @@ static inline void mv88e6xxx_reg_unlock(struct mv88e6xxx_chip *chip)
mutex_unlock(&chip->reg_lock);
}
int mv88e6xxx_vtu_walk(struct mv88e6xxx_chip *chip,
int (*cb)(struct mv88e6xxx_chip *chip,
const struct mv88e6xxx_vtu_entry *entry,
void *priv),
void *priv);
int mv88e6xxx_fid_map(struct mv88e6xxx_chip *chip, unsigned long *bitmap);
#endif /* _MV88E6XXX_CHIP_H */
......@@ -12,6 +12,7 @@
#include "chip.h"
#include "global1.h"
#include "switchdev.h"
#include "trace.h"
/* Offset 0x01: ATU FID Register */
......@@ -409,23 +410,25 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
err = mv88e6xxx_g1_read_atu_violation(chip);
if (err)
goto out;
goto out_unlock;
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_OP, &val);
if (err)
goto out;
goto out_unlock;
err = mv88e6xxx_g1_atu_fid_read(chip, &fid);
if (err)
goto out;
goto out_unlock;
err = mv88e6xxx_g1_atu_data_read(chip, &entry);
if (err)
goto out;
goto out_unlock;
err = mv88e6xxx_g1_atu_mac_read(chip, &entry);
if (err)
goto out;
goto out_unlock;
mv88e6xxx_reg_unlock(chip);
spid = entry.state;
......@@ -441,6 +444,13 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
entry.portvec, entry.mac,
fid);
chip->ports[spid].atu_miss_violation++;
if (fid != MV88E6XXX_FID_STANDALONE && chip->ports[spid].mab) {
err = mv88e6xxx_handle_miss_violation(chip, spid,
&entry, fid);
if (err)
goto out;
}
}
if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) {
......@@ -449,13 +459,13 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
fid);
chip->ports[spid].atu_full_violation++;
}
mv88e6xxx_reg_unlock(chip);
return IRQ_HANDLED;
out:
out_unlock:
mv88e6xxx_reg_unlock(chip);
out:
dev_err(chip->dev, "ATU problem: error %d while handling interrupt\n",
err);
return IRQ_HANDLED;
......
// 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;
}
/* SPDX-License-Identifier: GPL-2.0-or-later
*
* switchdev.h
*
* Authors:
* Hans J. Schultz <netdev@kapio-technology.com>
*
*/
#ifndef _MV88E6XXX_SWITCHDEV_H_
#define _MV88E6XXX_SWITCHDEV_H_
#include "chip.h"
int mv88e6xxx_handle_miss_violation(struct mv88e6xxx_chip *chip, int port,
struct mv88e6xxx_atu_entry *entry,
u16 fid);
#endif /* _MV88E6XXX_SWITCHDEV_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment