From: Vladimir Oltean <olteanv@gmail.com>
To: Tobias Waldekranz <tobias@waldekranz.com>
Cc: davem@davemloft.net, kuba@kernel.org, andrew@lunn.ch,
vivien.didelot@gmail.com, f.fainelli@gmail.com,
netdev@vger.kernel.org, robh+dt@kernel.org,
devicetree@vger.kernel.org
Subject: Re: [PATCH v2 net-next 4/5] net: dsa: Allow default tag protocol to be overridden from DT
Date: Thu, 15 Apr 2021 19:54:20 +0300 [thread overview]
Message-ID: <20210415165420.pb5mgxyzhezqnvh5@skbuf> (raw)
In-Reply-To: <20210415092610.953134-5-tobias@waldekranz.com>
On Thu, Apr 15, 2021 at 11:26:09AM +0200, Tobias Waldekranz wrote:
> Some combinations of tag protocols and Ethernet controllers are
> incompatible, and it is hard for the driver to keep track of these.
>
> Therefore, allow the device tree author (typically the board vendor)
> to inform the driver of this fact by selecting an alternate protocol
> that is known to work.
>
> Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
> ---
> include/net/dsa.h | 5 +++
> net/dsa/dsa2.c | 95 ++++++++++++++++++++++++++++++++++++++---------
> 2 files changed, 83 insertions(+), 17 deletions(-)
>
> diff --git a/include/net/dsa.h b/include/net/dsa.h
> index 1259b0f40684..2b25fe1ad5b7 100644
> --- a/include/net/dsa.h
> +++ b/include/net/dsa.h
> @@ -149,6 +149,11 @@ struct dsa_switch_tree {
> /* Tagging protocol operations */
> const struct dsa_device_ops *tag_ops;
>
> + /* Default tagging protocol preferred by the switches in this
> + * tree.
> + */
> + enum dsa_tag_protocol default_proto;
> +
> /*
> * Configuration data for the platform device that owns
> * this dsa switch tree instance.
> diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
> index d7c22e3a1fbf..80dbf8b6bf8f 100644
> --- a/net/dsa/dsa2.c
> +++ b/net/dsa/dsa2.c
> @@ -668,6 +668,35 @@ static const struct devlink_ops dsa_devlink_ops = {
> .sb_occ_tc_port_bind_get = dsa_devlink_sb_occ_tc_port_bind_get,
> };
>
> +static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds)
> +{
> + const struct dsa_device_ops *tag_ops = ds->dst->tag_ops;
> + struct dsa_switch_tree *dst = ds->dst;
> + int port, err;
> +
> + if (tag_ops->proto == dst->default_proto)
> + return 0;
> +
> + if (!ds->ops->change_tag_protocol) {
> + dev_err(ds->dev, "Tag protocol cannot be modified\n");
> + return -EINVAL;
> + }
We validated this already here:
if (ds->ops->change_tag_protocol) {
tag_ops = dsa_find_tagger_by_name(user_protocol);
} else {
dev_err(ds->dev, "Tag protocol cannot be modified\n");
return -EINVAL;
}
> +
> + for (port = 0; port < ds->num_ports; port++) {
> + if (!dsa_is_cpu_port(ds, port))
> + continue;
> +
> + err = ds->ops->change_tag_protocol(ds, port, tag_ops->proto);
> + if (err) {
> + dev_err(ds->dev, "Tag protocol \"%s\" is not supported\n",
> + tag_ops->name);
Maybe instead of saying "is not supported", you can say
"Changing the tag protocol to \"%s\" returned %pe", tag_ops->name, ERR_PTR(err)
which is a bit more informative.
> + return err;
> + }
> + }
> +
> + return 0;
> +}
> +
> static int dsa_switch_setup(struct dsa_switch *ds)
> {
> struct dsa_devlink_priv *dl_priv;
> @@ -718,6 +747,10 @@ static int dsa_switch_setup(struct dsa_switch *ds)
> if (err < 0)
> goto unregister_notifier;
>
> + err = dsa_switch_setup_tag_protocol(ds);
> + if (err)
> + goto teardown;
> +
> devlink_params_publish(ds->devlink);
>
> if (!ds->slave_mii_bus && ds->ops->phy_read) {
> @@ -1068,34 +1101,60 @@ static enum dsa_tag_protocol dsa_get_tag_protocol(struct dsa_port *dp,
> return ds->ops->get_tag_protocol(ds, dp->index, tag_protocol);
> }
>
> -static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master)
> +static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master,
> + const char *user_protocol)
> {
> struct dsa_switch *ds = dp->ds;
> struct dsa_switch_tree *dst = ds->dst;
> const struct dsa_device_ops *tag_ops;
> - enum dsa_tag_protocol tag_protocol;
> + enum dsa_tag_protocol default_proto;
> +
> + /* Find out which protocol the switch would prefer. */
> + default_proto = dsa_get_tag_protocol(dp, master);
> + if (dst->default_proto) {
> + if (dst->default_proto != default_proto) {
> + dev_err(ds->dev,
> + "A DSA switch tree can have only one tagging protocol\n");
> + return -EINVAL;
> + }
> + } else {
> + dst->default_proto = default_proto;
> + }
> +
> + /* See if the user wants to override that preference. */
> + if (user_protocol) {
> + if (ds->ops->change_tag_protocol) {
> + tag_ops = dsa_find_tagger_by_name(user_protocol);
> + } else {
> + dev_err(ds->dev, "Tag protocol cannot be modified\n");
> + return -EINVAL;
> + }
Your choice, but how about:
if (!ds->ops->change_tag_protocol) {
dev_err(ds->dev, "Tag protocol cannot be modified\n");
return -EINVAL;
}
tag_ops = dsa_find_tagger_by_name(user_protocol);
> + } else {
> + tag_ops = dsa_tag_driver_get(default_proto);
> + }
> +
> + if (IS_ERR(tag_ops)) {
> + if (PTR_ERR(tag_ops) == -ENOPROTOOPT)
> + return -EPROBE_DEFER;
> +
> + dev_warn(ds->dev, "No tagger for this switch\n");
> + return PTR_ERR(tag_ops);
> + }
>
> - tag_protocol = dsa_get_tag_protocol(dp, master);
> if (dst->tag_ops) {
> - if (dst->tag_ops->proto != tag_protocol) {
> + if (dst->tag_ops != tag_ops) {
> dev_err(ds->dev,
> "A DSA switch tree can have only one tagging protocol\n");
> +
> + dsa_tag_driver_put(tag_ops);
> return -EINVAL;
> }
> +
> /* In the case of multiple CPU ports per switch, the tagging
> - * protocol is still reference-counted only per switch tree, so
> - * nothing to do here.
> + * protocol is still reference-counted only per switch tree.
> */
> + dsa_tag_driver_put(tag_ops);
> } else {
> - tag_ops = dsa_tag_driver_get(tag_protocol);
> - if (IS_ERR(tag_ops)) {
> - if (PTR_ERR(tag_ops) == -ENOPROTOOPT)
> - return -EPROBE_DEFER;
> - dev_warn(ds->dev, "No tagger for this switch\n");
> - dp->master = NULL;
> - return PTR_ERR(tag_ops);
> - }
> -
> dst->tag_ops = tag_ops;
So at the end of dsa_port_parse_cpu, we have a dst->tag_ops which is
temporarily out of sync with the driver. We call dsa_port_set_tag_protocol()
with the new tagging protocol _before_ we call ds->ops->change_tag_protocol.
But as opposed to dsa_switch_change_tag_proto(), if ds->ops->change_tag_protocol
fails from the probe path, we treat it as a catastrophic error. So at
the end there is no risk of having anything out of sync I believe.
Maybe you should write this down in a comment? The logic is pretty
convoluted and hard to follow.
> }
>
> @@ -1117,12 +1176,14 @@ static int dsa_port_parse_of(struct dsa_port *dp, struct device_node *dn)
>
> if (ethernet) {
> struct net_device *master;
> + const char *user_protocol;
>
> master = of_find_net_device_by_node(ethernet);
> if (!master)
> return -EPROBE_DEFER;
>
> - return dsa_port_parse_cpu(dp, master);
> + user_protocol = of_get_property(dn, "dsa,tag-protocol", NULL);
> + return dsa_port_parse_cpu(dp, master, user_protocol);
> }
>
> if (link)
> @@ -1234,7 +1295,7 @@ static int dsa_port_parse(struct dsa_port *dp, const char *name,
>
> dev_put(master);
>
> - return dsa_port_parse_cpu(dp, master);
> + return dsa_port_parse_cpu(dp, master, NULL);
> }
>
> if (!strcmp(name, "dsa"))
> --
> 2.25.1
>
next prev parent reply other threads:[~2021-04-15 16:54 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-15 9:26 [PATCH v2 net-next 0/5] net: dsa: Allow default tag protocol to be overridden from DT Tobias Waldekranz
2021-04-15 9:26 ` [PATCH v2 net-next 1/5] net: dsa: mv88e6xxx: Mark chips with undocumented EDSA tag support Tobias Waldekranz
2021-04-15 16:04 ` Vladimir Oltean
2021-04-15 16:12 ` Florian Fainelli
2021-04-15 9:26 ` [PATCH v2 net-next 2/5] net: dsa: mv88e6xxx: Allow dynamic reconfiguration of tag protocol Tobias Waldekranz
2021-04-15 16:06 ` Vladimir Oltean
2021-04-15 16:12 ` Florian Fainelli
2021-04-15 9:26 ` [PATCH v2 net-next 3/5] net: dsa: Only notify CPU ports of changes to the " Tobias Waldekranz
2021-04-15 16:07 ` Vladimir Oltean
2021-04-15 16:36 ` Florian Fainelli
2021-04-15 9:26 ` [PATCH v2 net-next 4/5] net: dsa: Allow default tag protocol to be overridden from DT Tobias Waldekranz
2021-04-15 16:54 ` Vladimir Oltean [this message]
2021-04-15 9:26 ` [PATCH v2 net-next 5/5] dt-bindings: net: dsa: Document dsa,tag-protocol property Tobias Waldekranz
2021-04-15 21:27 ` Rob Herring
2021-04-19 18:55 ` Vladimir Oltean
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=20210415165420.pb5mgxyzhezqnvh5@skbuf \
--to=olteanv@gmail.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=devicetree@vger.kernel.org \
--cc=f.fainelli@gmail.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=robh+dt@kernel.org \
--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