netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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 v8 15/16] net: dsa: qca8k: add support for larger read/write size with mgmt Ethernet
Date: Wed,  2 Feb 2022 01:03:34 +0100	[thread overview]
Message-ID: <20220202000335.19296-16-ansuelsmth@gmail.com> (raw)
In-Reply-To: <20220202000335.19296-1-ansuelsmth@gmail.com>

mgmt Ethernet packet can read/write up to 16byte at times. The len reg
is limited to 15 (0xf). The switch actually sends and accepts data in 4
different steps of len values.
Len steps:
- 0: nothing
- 1-4: first 4 byte
- 5-6: first 12 byte
- 7-15: all 16 byte

In the alloc skb function we check if the len is 16 and we fix it to a
len of 15. It the read/write function interest to extract the real asked
data. The tagger handler will always copy the fully 16byte with a READ
command. This is useful for some big regs like the fdb reg that are
more than 4byte of data. This permits to introduce a bulk function that
will send and request the entire entry in one go.
Write function is changed and it does now require to pass the pointer to
val to also handle array val.

Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
 drivers/net/dsa/qca8k.c | 61 +++++++++++++++++++++++++++--------------
 1 file changed, 41 insertions(+), 20 deletions(-)

diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 0cce3a6030af..a1b76dcd2eb6 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -222,7 +222,9 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb)
 	if (cmd == MDIO_READ) {
 		mgmt_eth_data->data[0] = mgmt_ethhdr->mdio_data;
 
-		/* Get the rest of the 12 byte of data */
+		/* Get the rest of the 12 byte of data.
+		 * The read/write function will extract the requested data.
+		 */
 		if (len > QCA_HDR_MGMT_DATA1_LEN)
 			memcpy(mgmt_eth_data->data + 1, skb->data,
 			       QCA_HDR_MGMT_DATA2_LEN);
@@ -232,16 +234,30 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb)
 }
 
 static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 *val,
-					       int priority)
+					       int priority, unsigned int len)
 {
 	struct qca_mgmt_ethhdr *mgmt_ethhdr;
+	unsigned int real_len;
 	struct sk_buff *skb;
+	u32 *data2;
 	u16 hdr;
 
 	skb = dev_alloc_skb(QCA_HDR_MGMT_PKT_LEN);
 	if (!skb)
 		return NULL;
 
+	/* Max value for len reg is 15 (0xf) but the switch actually return 16 byte
+	 * Actually for some reason the steps are:
+	 * 0: nothing
+	 * 1-4: first 4 byte
+	 * 5-6: first 12 byte
+	 * 7-15: all 16 byte
+	 */
+	if (len == 16)
+		real_len = 15;
+	else
+		real_len = len;
+
 	skb_reset_mac_header(skb);
 	skb_set_network_header(skb, skb->len);
 
@@ -254,7 +270,7 @@ static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 *
 	hdr |= FIELD_PREP(QCA_HDR_XMIT_CONTROL, QCA_HDR_XMIT_TYPE_RW_REG);
 
 	mgmt_ethhdr->command = FIELD_PREP(QCA_HDR_MGMT_ADDR, reg);
-	mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_LENGTH, 4);
+	mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_LENGTH, real_len);
 	mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_CMD, cmd);
 	mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_CHECK_CODE,
 					   QCA_HDR_MGMT_CHECK_CODE_VAL);
@@ -264,7 +280,9 @@ static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 *
 
 	mgmt_ethhdr->hdr = htons(hdr);
 
-	skb_put_zero(skb, QCA_HDR_MGMT_DATA2_LEN + QCA_HDR_MGMT_PADDING_LEN);
+	data2 = skb_put_zero(skb, QCA_HDR_MGMT_DATA2_LEN + QCA_HDR_MGMT_PADDING_LEN);
+	if (cmd == MDIO_WRITE && len > QCA_HDR_MGMT_DATA1_LEN)
+		memcpy(data2, val + 1, len - QCA_HDR_MGMT_DATA1_LEN);
 
 	return skb;
 }
@@ -277,7 +295,7 @@ static void qca8k_mdio_header_fill_seq_num(struct sk_buff *skb, u32 seq_num)
 	mgmt_ethhdr->seq = FIELD_PREP(QCA_HDR_MGMT_SEQ_NUM, seq_num);
 }
 
-static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val)
+static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
 {
 	struct qca8k_mgmt_eth_data *mgmt_eth_data = &priv->mgmt_eth_data;
 	struct sk_buff *skb;
@@ -285,7 +303,7 @@ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val)
 	int ret;
 
 	skb = qca8k_alloc_mdio_header(MDIO_READ, reg, NULL,
-				      QCA8K_ETHERNET_MDIO_PRIORITY);
+				      QCA8K_ETHERNET_MDIO_PRIORITY, len);
 	if (!skb)
 		return -ENOMEM;
 
@@ -313,6 +331,9 @@ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val)
 					  msecs_to_jiffies(QCA8K_ETHERNET_TIMEOUT));
 
 	*val = mgmt_eth_data->data[0];
+	if (len > QCA_HDR_MGMT_DATA1_LEN)
+		memcpy(val + 1, mgmt_eth_data->data + 1, len - QCA_HDR_MGMT_DATA1_LEN);
+
 	ack = mgmt_eth_data->ack;
 
 	mutex_unlock(&mgmt_eth_data->mutex);
@@ -326,15 +347,15 @@ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val)
 	return 0;
 }
 
-static int qca8k_write_eth(struct qca8k_priv *priv, u32 reg, u32 val)
+static int qca8k_write_eth(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
 {
 	struct qca8k_mgmt_eth_data *mgmt_eth_data = &priv->mgmt_eth_data;
 	struct sk_buff *skb;
 	bool ack;
 	int ret;
 
-	skb = qca8k_alloc_mdio_header(MDIO_WRITE, reg, &val,
-				      QCA8K_ETHERNET_MDIO_PRIORITY);
+	skb = qca8k_alloc_mdio_header(MDIO_WRITE, reg, val,
+				      QCA8K_ETHERNET_MDIO_PRIORITY, len);
 	if (!skb)
 		return -ENOMEM;
 
@@ -380,14 +401,14 @@ qca8k_regmap_update_bits_eth(struct qca8k_priv *priv, u32 reg, u32 mask, u32 wri
 	u32 val = 0;
 	int ret;
 
-	ret = qca8k_read_eth(priv, reg, &val);
+	ret = qca8k_read_eth(priv, reg, &val, sizeof(val));
 	if (ret)
 		return ret;
 
 	val &= ~mask;
 	val |= write_val;
 
-	return qca8k_write_eth(priv, reg, val);
+	return qca8k_write_eth(priv, reg, &val, sizeof(val));
 }
 
 static int
@@ -398,7 +419,7 @@ qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
 	u16 r1, r2, page;
 	int ret;
 
-	if (!qca8k_read_eth(priv, reg, val))
+	if (!qca8k_read_eth(priv, reg, val, sizeof(val)))
 		return 0;
 
 	qca8k_split_addr(reg, &r1, &r2, &page);
@@ -424,7 +445,7 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
 	u16 r1, r2, page;
 	int ret;
 
-	if (!qca8k_write_eth(priv, reg, val))
+	if (!qca8k_write_eth(priv, reg, &val, sizeof(val)))
 		return 0;
 
 	qca8k_split_addr(reg, &r1, &r2, &page);
@@ -959,21 +980,21 @@ qca8k_phy_eth_command(struct qca8k_priv *priv, bool read, int phy,
 	}
 
 	/* Prealloc all the needed skb before the lock */
-	write_skb = qca8k_alloc_mdio_header(MDIO_WRITE, QCA8K_MDIO_MASTER_CTRL,
-					    &write_val, QCA8K_ETHERNET_PHY_PRIORITY);
+	write_skb = qca8k_alloc_mdio_header(MDIO_WRITE, QCA8K_MDIO_MASTER_CTRL, &write_val,
+					    QCA8K_ETHERNET_PHY_PRIORITY, sizeof(write_val));
 	if (!write_skb)
 		return -ENOMEM;
 
-	clear_skb = qca8k_alloc_mdio_header(MDIO_WRITE, QCA8K_MDIO_MASTER_CTRL,
-					    &clear_val, QCA8K_ETHERNET_PHY_PRIORITY);
+	clear_skb = qca8k_alloc_mdio_header(MDIO_WRITE, QCA8K_MDIO_MASTER_CTRL, &clear_val,
+					    QCA8K_ETHERNET_PHY_PRIORITY, sizeof(clear_val));
 	if (!write_skb) {
 		ret = -ENOMEM;
 		goto err_clear_skb;
 	}
 
-	read_skb = qca8k_alloc_mdio_header(MDIO_READ, QCA8K_MDIO_MASTER_CTRL,
-					   &clear_val, QCA8K_ETHERNET_PHY_PRIORITY);
-	if (!write_skb) {
+	read_skb = qca8k_alloc_mdio_header(MDIO_READ, QCA8K_MDIO_MASTER_CTRL, &clear_val,
+					   QCA8K_ETHERNET_PHY_PRIORITY, sizeof(clear_val));
+	if (!read_skb) {
 		ret = -ENOMEM;
 		goto err_read_skb;
 	}
-- 
2.33.1


  parent reply	other threads:[~2022-02-02  0:04 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-02  0:03 [net-next PATCH v8 00/16] Add support for qca8k mdio rw in Ethernet packet Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 01/16] net: dsa: provide switch operations for tracking the master state Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 02/16] net: dsa: replay master state events in dsa_tree_{setup,teardown}_master Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 03/16] net: dsa: tag_qca: convert to FIELD macro Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 04/16] net: dsa: tag_qca: move define to include linux/dsa Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 05/16] net: dsa: tag_qca: enable promisc_on_master flag Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 06/16] net: dsa: tag_qca: add define for handling mgmt Ethernet packet Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 07/16] net: dsa: tag_qca: add define for handling MIB packet Ansuel Smith
2022-02-02  2:56   ` Florian Fainelli
2022-02-02  0:03 ` [net-next PATCH v8 08/16] net: dsa: tag_qca: add support for handling mgmt and MIB Ethernet packet Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 09/16] net: dsa: qca8k: add tracking state of master port Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 10/16] net: dsa: qca8k: add support for mgmt read/write in Ethernet packet Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 11/16] net: dsa: qca8k: add support for mib autocast " Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 12/16] net: dsa: qca8k: add support for phy read/write with mgmt Ethernet Ansuel Smith
2022-02-02  0:03 ` [net-next PATCH v8 13/16] net: dsa: qca8k: move page cache to driver priv Ansuel Smith
2022-02-02  2:57   ` Florian Fainelli
2022-02-02  0:03 ` [net-next PATCH v8 14/16] net: dsa: qca8k: cache lo and hi for mdio write Ansuel Smith
2022-02-02  0:03 ` Ansuel Smith [this message]
2022-02-02  0:03 ` [net-next PATCH v8 16/16] net: dsa: qca8k: introduce qca8k_bulk_read/write function Ansuel Smith
2022-02-02 14:50 ` [net-next PATCH v8 00/16] Add support for qca8k mdio rw in Ethernet packet patchwork-bot+netdevbpf

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=20220202000335.19296-16-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).