From: Ansuel Smith <ansuelsmth@gmail.com>
To: Andrew Lunn <andrew@lunn.ch>,
Vivien Didelot <vivien.didelot@gmail.com>,
Florian Fainelli <f.fainelli@gmail.com>,
Vladimir Oltean <olteanv@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>,
linux-kernel@vger.kernel.org, netdev@vger.kernel.org
Cc: Ansuel Smith <ansuelsmth@gmail.com>
Subject: [net-next PATCH RFC v6 13/16] net: dsa: qca8k: add support for mib autocast in Ethernet packet
Date: Tue, 14 Dec 2021 23:44:06 +0100 [thread overview]
Message-ID: <20211214224409.5770-14-ansuelsmth@gmail.com> (raw)
In-Reply-To: <20211214224409.5770-1-ansuelsmth@gmail.com>
The switch can autocast MIB counter using Ethernet packet.
Add support for this and provide a handler for the tagger.
The switch will send packet with MIB counter for each port, the switch
will use completion API to wait for the correct packet to be received
and will complete the task only when each packet is received.
Although the handler will drop all the other packet, we still have to
consume each MIB packet to complete the request. This is done to prevent
mixed data with concurrent ethtool request.
connect_tag_protocol() is used to add the handler to the tag_qca tagger,
master_state_change() use the MIB lock to make sure no MIB Ethernet is
in progress.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
drivers/net/dsa/qca8k.c | 106 +++++++++++++++++++++++++++++++++++++++-
drivers/net/dsa/qca8k.h | 17 ++++++-
2 files changed, 121 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index b35ba26a0696..15f265c6ef02 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -795,7 +795,10 @@ qca8k_mib_init(struct qca8k_priv *priv)
int ret;
mutex_lock(&priv->reg_mutex);
- ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
+ ret = regmap_update_bits(priv->regmap, QCA8K_REG_MIB,
+ QCA8K_MIB_FUNC | QCA8K_MIB_BUSY,
+ FIELD_PREP(QCA8K_MIB_FUNC, QCA8K_MIB_FLUSH) |
+ QCA8K_MIB_BUSY);
if (ret)
goto exit;
@@ -1866,6 +1869,97 @@ qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data)
ETH_GSTRING_LEN);
}
+static void qca8k_mib_autocast_handler(struct dsa_port *dp, struct sk_buff *skb)
+{
+ const struct qca8k_match_data *match_data;
+ struct qca8k_mib_hdr_data *mib_hdr_data;
+ struct qca8k_priv *priv = dp->ds->priv;
+ const struct qca8k_mib_desc *mib;
+ struct mib_ethhdr *mib_ethhdr;
+ int i, mib_len, offset = 0;
+ u64 *data;
+ u8 port;
+
+ mib_ethhdr = (struct mib_ethhdr *)skb_mac_header(skb);
+ mib_hdr_data = &priv->mib_hdr_data;
+
+ /* The switch autocast every port. Ignore other packet and
+ * parse only the requested one.
+ */
+ port = FIELD_GET(QCA_HDR_RECV_SOURCE_PORT, ntohs(mib_ethhdr->hdr));
+ if (port != mib_hdr_data->req_port)
+ goto exit;
+
+ match_data = device_get_match_data(priv->dev);
+ data = mib_hdr_data->data;
+
+ for (i = 0; i < match_data->mib_count; i++) {
+ mib = &ar8327_mib[i];
+
+ /* First 3 mib are present in the skb head */
+ if (i < 3) {
+ data[i] = mib_ethhdr->data[i];
+ continue;
+ }
+
+ mib_len = sizeof(uint32_t);
+
+ /* Some mib are 64 bit wide */
+ if (mib->size == 2)
+ mib_len = sizeof(uint64_t);
+
+ /* Copy the mib value from packet to the */
+ memcpy(data + i, skb->data + offset, mib_len);
+
+ /* Set the offset for the next mib */
+ offset += mib_len;
+ }
+
+exit:
+ /* Complete on receiving all the mib packet */
+ if (refcount_dec_and_test(&mib_hdr_data->port_parsed))
+ complete(&mib_hdr_data->rw_done);
+}
+
+static int
+qca8k_get_ethtool_stats_eth(struct dsa_switch *ds, int port, u64 *data)
+{
+ struct dsa_port *dp = dsa_to_port(ds, port);
+ struct qca8k_mib_hdr_data *mib_hdr_data;
+ struct qca8k_priv *priv = ds->priv;
+ int ret;
+
+ mib_hdr_data = &priv->mib_hdr_data;
+
+ mutex_lock(&mib_hdr_data->mutex);
+
+ reinit_completion(&mib_hdr_data->rw_done);
+
+ mib_hdr_data->req_port = dp->index;
+ mib_hdr_data->data = data;
+ refcount_set(&mib_hdr_data->port_parsed, QCA8K_NUM_PORTS);
+
+ mutex_lock(&priv->reg_mutex);
+
+ /* Send mib autocast request */
+ ret = regmap_update_bits(priv->regmap, QCA8K_REG_MIB,
+ QCA8K_MIB_FUNC | QCA8K_MIB_BUSY,
+ FIELD_PREP(QCA8K_MIB_FUNC, QCA8K_MIB_CAST) |
+ QCA8K_MIB_BUSY);
+
+ mutex_unlock(&priv->reg_mutex);
+
+ if (ret)
+ goto exit;
+
+ ret = wait_for_completion_timeout(&mib_hdr_data->rw_done, QCA8K_ETHERNET_TIMEOUT);
+
+exit:
+ mutex_unlock(&mib_hdr_data->mutex);
+
+ return ret;
+}
+
static void
qca8k_get_ethtool_stats(struct dsa_switch *ds, int port,
uint64_t *data)
@@ -1877,6 +1971,10 @@ qca8k_get_ethtool_stats(struct dsa_switch *ds, int port,
u32 hi = 0;
int ret;
+ if (priv->master &&
+ qca8k_get_ethtool_stats_eth(ds, port, data) > 0)
+ return;
+
match_data = of_device_get_match_data(priv->dev);
for (i = 0; i < match_data->mib_count; i++) {
@@ -2558,6 +2656,7 @@ qca8k_master_change(struct dsa_switch *ds, const struct net_device *master,
return;
mutex_lock(&priv->mdio_hdr_data.mutex);
+ mutex_lock(&priv->mib_hdr_data.mutex);
if (operational)
priv->master = master;
@@ -2565,6 +2664,7 @@ qca8k_master_change(struct dsa_switch *ds, const struct net_device *master,
priv->master = NULL;
mutex_unlock(&priv->mdio_hdr_data.mutex);
+ mutex_unlock(&priv->mib_hdr_data.mutex);
}
static int qca8k_connect_tag_protocol(struct dsa_switch *ds,
@@ -2581,7 +2681,11 @@ static int qca8k_connect_tag_protocol(struct dsa_switch *ds,
mutex_init(&qca8k_priv->mdio_hdr_data.mutex);
init_completion(&qca8k_priv->mdio_hdr_data.rw_done);
+ mutex_init(&qca8k_priv->mib_hdr_data.mutex);
+ init_completion(&qca8k_priv->mib_hdr_data.rw_done);
+
priv->rw_reg_ack_handler = qca8k_rw_reg_ack_handler;
+ priv->mib_autocast_handler = qca8k_mib_autocast_handler;
break;
default:
diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
index dbe8c74c9793..4aca07db0192 100644
--- a/drivers/net/dsa/qca8k.h
+++ b/drivers/net/dsa/qca8k.h
@@ -67,7 +67,7 @@
#define QCA8K_REG_MODULE_EN 0x030
#define QCA8K_MODULE_EN_MIB BIT(0)
#define QCA8K_REG_MIB 0x034
-#define QCA8K_MIB_FLUSH BIT(24)
+#define QCA8K_MIB_FUNC GENMASK(26, 24)
#define QCA8K_MIB_CPU_KEEP BIT(20)
#define QCA8K_MIB_BUSY BIT(17)
#define QCA8K_MDIO_MASTER_CTRL 0x3c
@@ -317,6 +317,12 @@ enum qca8k_vlan_cmd {
QCA8K_VLAN_READ = 6,
};
+enum qca8k_mid_cmd {
+ QCA8K_MIB_FLUSH = 1,
+ QCA8K_MIB_FLUSH_PORT = 2,
+ QCA8K_MIB_CAST = 3,
+};
+
struct ar8xxx_port_status {
int enabled;
};
@@ -340,6 +346,14 @@ struct qca8k_mdio_hdr_data {
u32 data[4];
};
+struct qca8k_mib_hdr_data {
+ struct completion rw_done;
+ struct mutex mutex; /* Process one command at time */
+ refcount_t port_parsed; /* Counter to track parsed port */
+ u8 req_port;
+ u64 *data; /* pointer to ethtool data */
+};
+
struct qca8k_ports_config {
bool sgmii_rx_clk_falling_edge;
bool sgmii_tx_clk_falling_edge;
@@ -367,6 +381,7 @@ struct qca8k_priv {
unsigned int port_mtu[QCA8K_NUM_PORTS];
const struct net_device *master; /* Track if mdio/mib Ethernet is available */
struct qca8k_mdio_hdr_data mdio_hdr_data;
+ struct qca8k_mib_hdr_data mib_hdr_data;
};
struct qca8k_mib_desc {
--
2.33.1
next prev parent reply other threads:[~2021-12-14 22:45 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-14 22:43 [net-next PATCH RFC v6 00/16] Add support for qca8k mdio rw in Ethernet packet Ansuel Smith
2021-12-14 22:43 ` [net-next PATCH RFC v6 01/16] net: dsa: provide switch operations for tracking the master state Ansuel Smith
2021-12-14 22:43 ` [net-next PATCH RFC v6 02/16] net: dsa: stop updating master MTU from master.c Ansuel Smith
2021-12-14 22:43 ` [net-next PATCH RFC v6 03/16] net: dsa: hold rtnl_mutex when calling dsa_master_{setup,teardown} Ansuel Smith
2021-12-14 22:43 ` [net-next PATCH RFC v6 04/16] net: dsa: replay master state events in dsa_tree_{setup,teardown}_master Ansuel Smith
2021-12-14 22:43 ` [net-next PATCH RFC v6 05/16] net: dsa: tag_qca: convert to FIELD macro Ansuel Smith
2021-12-14 22:43 ` [net-next PATCH RFC v6 06/16] net: dsa: tag_qca: move define to include linux/dsa Ansuel Smith
2021-12-14 22:44 ` [net-next PATCH RFC v6 07/16] net: dsa: tag_qca: enable promisc_on_master flag Ansuel Smith
2021-12-15 9:58 ` Vladimir Oltean
2021-12-14 22:44 ` [net-next PATCH RFC v6 08/16] net: dsa: tag_qca: add define for handling mdio Ethernet packet Ansuel Smith
2021-12-15 9:58 ` Vladimir Oltean
2021-12-14 22:44 ` [net-next PATCH RFC v6 09/16] net: dsa: tag_qca: add define for handling MIB packet Ansuel Smith
2021-12-14 22:44 ` [net-next PATCH RFC v6 10/16] net: dsa: tag_qca: add support for handling mdio Ethernet and " Ansuel Smith
2021-12-15 9:54 ` Vladimir Oltean
2021-12-14 22:44 ` [net-next PATCH RFC v6 11/16] net: dsa: qca8k: add tracking state of master port Ansuel Smith
2021-12-15 9:51 ` Vladimir Oltean
2021-12-16 0:00 ` Ansuel Smith
2021-12-14 22:44 ` [net-next PATCH RFC v6 12/16] net: dsa: qca8k: add support for mdio read/write in Ethernet packet Ansuel Smith
2021-12-15 9:49 ` Vladimir Oltean
2021-12-15 16:53 ` Ansuel Smith
2021-12-15 12:47 ` Vladimir Oltean
2021-12-15 16:56 ` Ansuel Smith
2021-12-14 22:44 ` Ansuel Smith [this message]
2021-12-14 22:44 ` [net-next PATCH RFC v6 14/16] net: dsa: qca8k: add support for phy read/write with mdio Ethernet Ansuel Smith
2021-12-14 22:44 ` [net-next PATCH RFC v6 15/16] net: dsa: qca8k: move page cache to driver priv Ansuel Smith
2021-12-14 22:44 ` [net-next PATCH RFC v6 16/16] net: dsa: qca8k: cache lo and hi for mdio write Ansuel Smith
2021-12-14 23:34 ` [net-next PATCH RFC v6 00/16] Add support for qca8k mdio rw in Ethernet packet Ansuel Smith
2021-12-15 10:26 ` Vladimir Oltean
2021-12-15 16:34 ` Ansuel Smith
2021-12-16 23:38 ` Vladimir Oltean
2022-01-06 20:56 ` Ansuel Smith
2022-01-07 17:17 ` 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=20211214224409.5770-14-ansuelsmth@gmail.com \
--to=ansuelsmth@gmail.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=f.fainelli@gmail.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.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).