From: Vladimir Oltean <olteanv@gmail.com>
To: Tobias Waldekranz <tobias@waldekranz.com>
Cc: davem@davemloft.net, kuba@kernel.org,
Andrew Lunn <andrew@lunn.ch>,
Vivien Didelot <vivien.didelot@gmail.com>,
Florian Fainelli <f.fainelli@gmail.com>,
Jiri Pirko <jiri@resnulli.us>, Ivan Vecera <ivecera@redhat.com>,
Roopa Prabhu <roopa@nvidia.com>,
Nikolay Aleksandrov <razor@blackwall.org>,
Russell King <linux@armlinux.org.uk>,
Petr Machata <petrm@nvidia.com>, Cooper Lees <me@cooperlees.com>,
Ido Schimmel <idosch@nvidia.com>,
Matt Johnston <matt@codeconstruct.com.au>,
linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
bridge@lists.linux-foundation.org
Subject: Re: [PATCH v2 net-next 10/10] net: dsa: mv88e6xxx: MST Offloading
Date: Fri, 4 Mar 2022 00:26:58 +0200 [thread overview]
Message-ID: <20220303222658.7ykn6grkkp6htm7a@skbuf> (raw)
In-Reply-To: <20220301100321.951175-11-tobias@waldekranz.com>
On Tue, Mar 01, 2022 at 11:03:21AM +0100, Tobias Waldekranz wrote:
> Allocate a SID in the STU for each MSTID in use by a bridge and handle
> the mapping of MSTIDs to VLANs using the SID field of each VTU entry.
>
> Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
> ---
> drivers/net/dsa/mv88e6xxx/chip.c | 178 +++++++++++++++++++++++++++++++
> drivers/net/dsa/mv88e6xxx/chip.h | 13 +++
> 2 files changed, 191 insertions(+)
>
> diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
> index c14a62aa6a6c..4fb4ec1dff79 100644
> --- a/drivers/net/dsa/mv88e6xxx/chip.c
> +++ b/drivers/net/dsa/mv88e6xxx/chip.c
> @@ -1818,6 +1818,137 @@ static int mv88e6xxx_stu_setup(struct mv88e6xxx_chip *chip)
> return mv88e6xxx_stu_loadpurge(chip, &stu);
> }
>
> +static int mv88e6xxx_sid_new(struct mv88e6xxx_chip *chip, u8 *sid)
> +{
> + DECLARE_BITMAP(busy, MV88E6XXX_N_SID) = { 0 };
> + struct mv88e6xxx_mst *mst;
> +
> + set_bit(0, busy);
> +
> + list_for_each_entry(mst, &chip->msts, node) {
> + set_bit(mst->stu.sid, busy);
> + }
> +
> + *sid = find_first_zero_bit(busy, MV88E6XXX_N_SID);
> +
> + return (*sid >= mv88e6xxx_max_sid(chip)) ? -ENOSPC : 0;
> +}
> +
> +static int mv88e6xxx_sid_put(struct mv88e6xxx_chip *chip, u8 sid)
> +{
> + struct mv88e6xxx_mst *mst, *tmp;
> + int err = 0;
> +
> + list_for_each_entry_safe(mst, tmp, &chip->msts, node) {
> + if (mst->stu.sid == sid) {
> + if (refcount_dec_and_test(&mst->refcnt)) {
> + mst->stu.valid = false;
> + err = mv88e6xxx_stu_loadpurge(chip, &mst->stu);
It is interesting what to do if this fails. Possibly not this, because
the entry remains in hardware but not in software.
> + list_del(&mst->node);
> + kfree(mst);
> + }
> +
> + return err;
> + }
> + }
> +
> + return -ENOENT;
> +}
> +
> +static int mv88e6xxx_sid_get(struct mv88e6xxx_chip *chip, struct net_device *br,
> + u16 msti, u8 *sid)
> +{
> + struct mv88e6xxx_mst *mst;
> + int err, i;
> +
> + if (!br)
> + return 0;
Is this condition possible?
> +
> + if (!mv88e6xxx_has_stu(chip))
> + return -EOPNOTSUPP;
> +
> + list_for_each_entry(mst, &chip->msts, node) {
> + if (mst->br == br && mst->msti == msti) {
> + refcount_inc(&mst->refcnt);
> + *sid = mst->stu.sid;
> + return 0;
> + }
> + }
> +
> + err = mv88e6xxx_sid_new(chip, sid);
> + if (err)
> + return err;
> +
> + mst = kzalloc(sizeof(*mst), GFP_KERNEL);
> + if (!mst)
> + return -ENOMEM;
This leaks the new SID.
> +
> + INIT_LIST_HEAD(&mst->node);
> + refcount_set(&mst->refcnt, 1);
> + mst->br = br;
> + mst->msti = msti;
> + mst->stu.valid = true;
> + mst->stu.sid = *sid;
> +
> + /* The bridge starts out all ports in the disabled state. But
> + * a STU state of disabled means to go by the port-global
> + * state. So we set all user port's initial state to blocking,
> + * to match the bridge's behavior.
> + */
> + for (i = 0; i < mv88e6xxx_num_ports(chip); i++)
> + mst->stu.state[i] = dsa_is_user_port(chip->ds, i) ?
> + MV88E6XXX_PORT_CTL0_STATE_BLOCKING :
> + MV88E6XXX_PORT_CTL0_STATE_DISABLED;
> +
> + list_add_tail(&mst->node, &chip->msts);
> + return mv88e6xxx_stu_loadpurge(chip, &mst->stu);
And this doesn't behave too well on failure (the MSTID exists in
software but not in hardware).
> +}
> +
> +static int mv88e6xxx_port_mst_state_set(struct dsa_switch *ds, int port,
> + const struct switchdev_mst_state *st)
> +{
> + struct dsa_port *dp = dsa_to_port(ds, port);
> + struct mv88e6xxx_chip *chip = ds->priv;
> + struct mv88e6xxx_mst *mst;
> + u8 state;
> + int err;
> +
> + if (!mv88e6xxx_has_stu(chip))
> + return -EOPNOTSUPP;
> +
> + switch (st->state) {
> + case BR_STATE_DISABLED:
> + case BR_STATE_BLOCKING:
> + case BR_STATE_LISTENING:
> + state = MV88E6XXX_PORT_CTL0_STATE_BLOCKING;
> + break;
> + case BR_STATE_LEARNING:
> + state = MV88E6XXX_PORT_CTL0_STATE_LEARNING;
> + break;
> + case BR_STATE_FORWARDING:
> + state = MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + list_for_each_entry(mst, &chip->msts, node) {
> + if (mst->br == dsa_port_bridge_dev_get(dp) &&
> + mst->msti == st->msti) {
> + if (mst->stu.state[port] == state)
> + return 0;
> +
> + mst->stu.state[port] = state;
> + mv88e6xxx_reg_lock(chip);
> + err = mv88e6xxx_stu_loadpurge(chip, &mst->stu);
> + mv88e6xxx_reg_unlock(chip);
> + return err;
> + }
> + }
> +
> + return -ENOENT;
> +}
> +
> static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
> u16 vid)
> {
> @@ -2437,6 +2568,12 @@ static int mv88e6xxx_port_vlan_leave(struct mv88e6xxx_chip *chip,
> if (err)
> return err;
>
> + if (!vlan.valid && vlan.sid) {
> + err = mv88e6xxx_sid_put(chip, vlan.sid);
> + if (err)
> + return err;
> + }
> +
> return mv88e6xxx_g1_atu_remove(chip, vlan.fid, port, false);
> }
>
> @@ -2482,6 +2619,44 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
> return err;
> }
>
> +static int mv88e6xxx_vlan_msti_set(struct dsa_switch *ds,
> + const struct switchdev_attr *attr)
> +{
> + const struct switchdev_vlan_attr *vattr = &attr->u.vlan_attr;
> + struct mv88e6xxx_chip *chip = ds->priv;
> + struct mv88e6xxx_vtu_entry vlan;
> + u8 new_sid;
> + int err;
> +
> + mv88e6xxx_reg_lock(chip);
> +
> + err = mv88e6xxx_vtu_get(chip, vattr->vid, &vlan);
> + if (err)
> + goto unlock;
> +
> + if (!vlan.valid) {
> + err = -EINVAL;
> + goto unlock;
> + }
> +
> + err = mv88e6xxx_sid_get(chip, attr->orig_dev, vattr->msti, &new_sid);
> + if (err)
> + goto unlock;
> +
> + if (vlan.sid) {
> + err = mv88e6xxx_sid_put(chip, vlan.sid);
> + if (err)
> + goto unlock;
> + }
> +
> + vlan.sid = new_sid;
> + err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
Maybe you could move mv88e6xxx_sid_put() after this succeeds?
> +
> +unlock:
> + mv88e6xxx_reg_unlock(chip);
> + return err;
> +}
> +
> static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
> const unsigned char *addr, u16 vid,
> struct dsa_db db)
> @@ -6008,6 +6183,7 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
> mutex_init(&chip->reg_lock);
> INIT_LIST_HEAD(&chip->mdios);
> idr_init(&chip->policies);
> + INIT_LIST_HEAD(&chip->msts);
>
> return chip;
> }
> @@ -6540,10 +6716,12 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
> .port_pre_bridge_flags = mv88e6xxx_port_pre_bridge_flags,
> .port_bridge_flags = mv88e6xxx_port_bridge_flags,
> .port_stp_state_set = mv88e6xxx_port_stp_state_set,
> + .port_mst_state_set = mv88e6xxx_port_mst_state_set,
> .port_fast_age = mv88e6xxx_port_fast_age,
> .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
> .port_vlan_add = mv88e6xxx_port_vlan_add,
> .port_vlan_del = mv88e6xxx_port_vlan_del,
> + .vlan_msti_set = mv88e6xxx_vlan_msti_set,
> .port_fdb_add = mv88e6xxx_port_fdb_add,
> .port_fdb_del = mv88e6xxx_port_fdb_del,
> .port_fdb_dump = mv88e6xxx_port_fdb_dump,
> diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
> index 6d4daa24d3e5..6a0b66354e1d 100644
> --- a/drivers/net/dsa/mv88e6xxx/chip.h
> +++ b/drivers/net/dsa/mv88e6xxx/chip.h
> @@ -297,6 +297,16 @@ struct mv88e6xxx_region_priv {
> enum mv88e6xxx_region_id id;
> };
>
> +struct mv88e6xxx_mst {
> + struct list_head node;
> +
> + refcount_t refcnt;
> + struct net_device *br;
> + u16 msti;
> +
> + struct mv88e6xxx_stu_entry stu;
> +};
> +
> struct mv88e6xxx_chip {
> const struct mv88e6xxx_info *info;
>
> @@ -397,6 +407,9 @@ struct mv88e6xxx_chip {
>
> /* devlink regions */
> struct devlink_region *regions[_MV88E6XXX_REGION_MAX];
> +
> + /* Bridge MST to SID mappings */
> + struct list_head msts;
> };
>
> struct mv88e6xxx_bus_ops {
> --
> 2.25.1
>
next prev parent reply other threads:[~2022-03-03 22:27 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-01 10:03 [PATCH v2 net-next 00/10] net: bridge: Multiple Spanning Trees Tobias Waldekranz
2022-03-01 10:03 ` [PATCH v2 net-next 01/10] net: bridge: mst: Multiple Spanning Tree (MST) mode Tobias Waldekranz
2022-03-01 23:01 ` Nikolay Aleksandrov
2022-03-07 14:53 ` Tobias Waldekranz
2022-03-03 22:28 ` Vladimir Oltean
2022-03-01 10:03 ` [PATCH v2 net-next 02/10] net: bridge: mst: Allow changing a VLAN's MSTI Tobias Waldekranz
2022-03-03 22:27 ` Vladimir Oltean
2022-03-07 14:54 ` Tobias Waldekranz
2022-03-01 10:03 ` [PATCH v2 net-next 03/10] net: bridge: mst: Support setting and reporting MST port states Tobias Waldekranz
2022-03-01 23:19 ` Nikolay Aleksandrov
2022-03-02 1:53 ` Roopa Prabhu
2022-03-07 15:03 ` Tobias Waldekranz
2022-03-07 15:00 ` Tobias Waldekranz
2022-03-07 15:03 ` Nikolay Aleksandrov
2022-03-01 10:03 ` [PATCH v2 net-next 04/10] net: bridge: mst: Notify switchdev drivers of VLAN MSTI migrations Tobias Waldekranz
2022-03-03 20:59 ` Vladimir Oltean
2022-03-08 8:01 ` Tobias Waldekranz
2022-03-08 17:17 ` Vladimir Oltean
2022-03-09 15:34 ` Tobias Waldekranz
2022-03-01 10:03 ` [PATCH v2 net-next 05/10] net: bridge: mst: Notify switchdev drivers of MST state changes Tobias Waldekranz
2022-03-01 10:03 ` [PATCH v2 net-next 06/10] net: dsa: Pass VLAN MSTI migration notifications to driver Tobias Waldekranz
2022-03-03 22:29 ` Vladimir Oltean
2022-03-09 15:47 ` Tobias Waldekranz
2022-03-09 17:03 ` Vladimir Oltean
2022-03-01 10:03 ` [PATCH v2 net-next 07/10] net: dsa: Pass MST state changes " Tobias Waldekranz
2022-03-03 22:20 ` Vladimir Oltean
2022-03-10 8:54 ` Tobias Waldekranz
2022-03-10 10:35 ` Vladimir Oltean
2022-03-10 16:05 ` Tobias Waldekranz
2022-03-10 16:18 ` Vladimir Oltean
2022-03-10 22:46 ` Tobias Waldekranz
2022-03-10 23:08 ` Vladimir Oltean
2022-03-10 23:59 ` Tobias Waldekranz
2022-03-11 0:22 ` Vladimir Oltean
2022-03-11 9:01 ` Tobias Waldekranz
2022-03-10 16:20 ` Tobias Waldekranz
2022-03-01 10:03 ` [PATCH v2 net-next 08/10] net: dsa: mv88e6xxx: Disentangle STU from VTU Tobias Waldekranz
2022-03-01 10:03 ` [PATCH v2 net-next 09/10] net: dsa: mv88e6xxx: Export STU as devlink region Tobias Waldekranz
2022-03-01 10:03 ` [PATCH v2 net-next 10/10] net: dsa: mv88e6xxx: MST Offloading Tobias Waldekranz
2022-03-03 22:26 ` Vladimir Oltean [this message]
2022-03-10 15:14 ` Tobias Waldekranz
2022-03-10 15:25 ` Vladimir Oltean
2022-03-10 15:33 ` Vladimir Oltean
2022-03-01 16:21 ` [PATCH v2 net-next 00/10] net: bridge: Multiple Spanning Trees Vladimir Oltean
2022-03-01 17:19 ` Stephen Hemminger
2022-03-01 21:20 ` Tobias Waldekranz
2022-03-01 22:30 ` Pavel Šimerda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220303222658.7ykn6grkkp6htm7a@skbuf \
--to=olteanv@gmail.com \
--cc=andrew@lunn.ch \
--cc=bridge@lists.linux-foundation.org \
--cc=davem@davemloft.net \
--cc=f.fainelli@gmail.com \
--cc=idosch@nvidia.com \
--cc=ivecera@redhat.com \
--cc=jiri@resnulli.us \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=matt@codeconstruct.com.au \
--cc=me@cooperlees.com \
--cc=netdev@vger.kernel.org \
--cc=petrm@nvidia.com \
--cc=razor@blackwall.org \
--cc=roopa@nvidia.com \
--cc=tobias@waldekranz.com \
--cc=vivien.didelot@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).