[openwrt/openwrt] generic: 5.15: backport qca8k fixup patches for Big-Endian systems

LEDE Commits lede-commits at lists.infradead.org
Fri Oct 14 06:13:47 PDT 2022


ansuel pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/fcff86be06da37e1b0839d12efd4a5afc40e8973

commit fcff86be06da37e1b0839d12efd4a5afc40e8973
Author: Christian Marangi <ansuelsmth at gmail.com>
AuthorDate: Fri Oct 14 15:10:52 2022 +0200

    generic: 5.15: backport qca8k fixup patches for Big-Endian systems
    
    Backport qca8k fixup patches for inband mgmt on Big-Endian systems.
    This is needed for ath79 and mpc85xx targets that are Big-Endian and use
    qca8k based switch.
    
    Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 ...8k-fix-inband-mgmt-for-big-endian-systems.patch | 163 +++++++++++++++++++++
 ...8k-fix-ethtool-autocast-mib-for-big-endia.patch |  88 +++++++++++
 2 files changed, 251 insertions(+)

diff --git a/target/linux/generic/backport-5.15/776-v6.1-01-net-dsa-qca8k-fix-inband-mgmt-for-big-endian-systems.patch b/target/linux/generic/backport-5.15/776-v6.1-01-net-dsa-qca8k-fix-inband-mgmt-for-big-endian-systems.patch
new file mode 100644
index 0000000000..e706874a6a
--- /dev/null
+++ b/target/linux/generic/backport-5.15/776-v6.1-01-net-dsa-qca8k-fix-inband-mgmt-for-big-endian-systems.patch
@@ -0,0 +1,163 @@
+From a2550d3ce53c68f54042bc5e468c4d07491ffe0e Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at gmail.com>
+Date: Wed, 12 Oct 2022 19:18:36 +0200
+Subject: [PATCH 1/2] net: dsa: qca8k: fix inband mgmt for big-endian systems
+
+The header and the data of the skb for the inband mgmt requires
+to be in little-endian. This is problematic for big-endian system
+as the mgmt header is written in the cpu byte order.
+
+Fix this by converting each value for the mgmt header and data to
+little-endian, and convert to cpu byte order the mgmt header and
+data sent by the switch.
+
+Fixes: 5950c7c0a68c ("net: dsa: qca8k: add support for mgmt read/write in Ethernet packet")
+Tested-by: Pawel Dembicki <paweldembicki at gmail.com>
+Tested-by: Lech Perczak <lech.perczak at gmail.com>
+Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
+Reviewed-by: Lech Perczak <lech.perczak at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca/qca8k-8xxx.c | 63 ++++++++++++++++++++++++--------
+ include/linux/dsa/tag_qca.h      |  6 +--
+ 2 files changed, 50 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
+index 5669c92c93f7..644338ca0510 100644
+--- a/drivers/net/dsa/qca/qca8k-8xxx.c
++++ b/drivers/net/dsa/qca/qca8k-8xxx.c
+@@ -137,27 +137,42 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb)
+ 	struct qca8k_mgmt_eth_data *mgmt_eth_data;
+ 	struct qca8k_priv *priv = ds->priv;
+ 	struct qca_mgmt_ethhdr *mgmt_ethhdr;
++	u32 command;
+ 	u8 len, cmd;
++	int i;
+ 
+ 	mgmt_ethhdr = (struct qca_mgmt_ethhdr *)skb_mac_header(skb);
+ 	mgmt_eth_data = &priv->mgmt_eth_data;
+ 
+-	cmd = FIELD_GET(QCA_HDR_MGMT_CMD, mgmt_ethhdr->command);
+-	len = FIELD_GET(QCA_HDR_MGMT_LENGTH, mgmt_ethhdr->command);
++	command = get_unaligned_le32(&mgmt_ethhdr->command);
++	cmd = FIELD_GET(QCA_HDR_MGMT_CMD, command);
++	len = FIELD_GET(QCA_HDR_MGMT_LENGTH, command);
+ 
+ 	/* Make sure the seq match the requested packet */
+-	if (mgmt_ethhdr->seq == mgmt_eth_data->seq)
++	if (get_unaligned_le32(&mgmt_ethhdr->seq) == mgmt_eth_data->seq)
+ 		mgmt_eth_data->ack = true;
+ 
+ 	if (cmd == MDIO_READ) {
+-		mgmt_eth_data->data[0] = mgmt_ethhdr->mdio_data;
++		u32 *val = mgmt_eth_data->data;
++
++		*val = get_unaligned_le32(&mgmt_ethhdr->mdio_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);
++		if (len > QCA_HDR_MGMT_DATA1_LEN) {
++			__le32 *data2 = (__le32 *)skb->data;
++			int data_len = min_t(int, QCA_HDR_MGMT_DATA2_LEN,
++					     len - QCA_HDR_MGMT_DATA1_LEN);
++
++			val++;
++
++			for (i = sizeof(u32); i <= data_len; i += sizeof(u32)) {
++				*val = get_unaligned_le32(data2);
++				val++;
++				data2++;
++			}
++		}
+ 	}
+ 
+ 	complete(&mgmt_eth_data->rw_done);
+@@ -169,8 +184,10 @@ static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 *
+ 	struct qca_mgmt_ethhdr *mgmt_ethhdr;
+ 	unsigned int real_len;
+ 	struct sk_buff *skb;
+-	u32 *data2;
++	__le32 *data2;
++	u32 command;
+ 	u16 hdr;
++	int i;
+ 
+ 	skb = dev_alloc_skb(QCA_HDR_MGMT_PKT_LEN);
+ 	if (!skb)
+@@ -199,20 +216,32 @@ static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 *
+ 	hdr |= FIELD_PREP(QCA_HDR_XMIT_DP_BIT, BIT(0));
+ 	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, real_len);
+-	mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_CMD, cmd);
+-	mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_CHECK_CODE,
++	command = FIELD_PREP(QCA_HDR_MGMT_ADDR, reg);
++	command |= FIELD_PREP(QCA_HDR_MGMT_LENGTH, real_len);
++	command |= FIELD_PREP(QCA_HDR_MGMT_CMD, cmd);
++	command |= FIELD_PREP(QCA_HDR_MGMT_CHECK_CODE,
+ 					   QCA_HDR_MGMT_CHECK_CODE_VAL);
+ 
++	put_unaligned_le32(command, &mgmt_ethhdr->command);
++
+ 	if (cmd == MDIO_WRITE)
+-		mgmt_ethhdr->mdio_data = *val;
++		put_unaligned_le32(*val, &mgmt_ethhdr->mdio_data);
+ 
+ 	mgmt_ethhdr->hdr = htons(hdr);
+ 
+ 	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);
++	if (cmd == MDIO_WRITE && len > QCA_HDR_MGMT_DATA1_LEN) {
++		int data_len = min_t(int, QCA_HDR_MGMT_DATA2_LEN,
++				     len - QCA_HDR_MGMT_DATA1_LEN);
++
++		val++;
++
++		for (i = sizeof(u32); i <= data_len; i += sizeof(u32)) {
++			put_unaligned_le32(*val, data2);
++			data2++;
++			val++;
++		}
++	}
+ 
+ 	return skb;
+ }
+@@ -220,9 +249,11 @@ static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 *
+ static void qca8k_mdio_header_fill_seq_num(struct sk_buff *skb, u32 seq_num)
+ {
+ 	struct qca_mgmt_ethhdr *mgmt_ethhdr;
++	u32 seq;
+ 
++	seq = FIELD_PREP(QCA_HDR_MGMT_SEQ_NUM, seq_num);
+ 	mgmt_ethhdr = (struct qca_mgmt_ethhdr *)skb->data;
+-	mgmt_ethhdr->seq = FIELD_PREP(QCA_HDR_MGMT_SEQ_NUM, seq_num);
++	put_unaligned_le32(seq, &mgmt_ethhdr->seq);
+ }
+ 
+ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
+diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h
+index 50be7cbd93a5..0e176da1e43f 100644
+--- a/include/linux/dsa/tag_qca.h
++++ b/include/linux/dsa/tag_qca.h
+@@ -61,9 +61,9 @@ struct sk_buff;
+ 
+ /* Special struct emulating a Ethernet header */
+ struct qca_mgmt_ethhdr {
+-	u32 command;		/* command bit 31:0 */
+-	u32 seq;		/* seq 63:32 */
+-	u32 mdio_data;		/* first 4byte mdio */
++	__le32 command;		/* command bit 31:0 */
++	__le32 seq;		/* seq 63:32 */
++	__le32 mdio_data;		/* first 4byte mdio */
+ 	__be16 hdr;		/* qca hdr */
+ } __packed;
+ 
+-- 
+2.37.2
+
diff --git a/target/linux/generic/backport-5.15/776-v6.1-02-net-dsa-qca8k-fix-ethtool-autocast-mib-for-big-endia.patch b/target/linux/generic/backport-5.15/776-v6.1-02-net-dsa-qca8k-fix-ethtool-autocast-mib-for-big-endia.patch
new file mode 100644
index 0000000000..93c0bb85b5
--- /dev/null
+++ b/target/linux/generic/backport-5.15/776-v6.1-02-net-dsa-qca8k-fix-ethtool-autocast-mib-for-big-endia.patch
@@ -0,0 +1,88 @@
+From 0d4636f7d72df3179b20a2d32b647881917a5e2a Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at gmail.com>
+Date: Wed, 12 Oct 2022 19:18:37 +0200
+Subject: [PATCH 2/2] net: dsa: qca8k: fix ethtool autocast mib for big-endian
+ systems
+
+The switch sends autocast mib in little-endian. This is problematic for
+big-endian system as the values needs to be converted.
+
+Fix this by converting each mib value to cpu byte order.
+
+Fixes: 5c957c7ca78c ("net: dsa: qca8k: add support for mib autocast in Ethernet packet")
+Tested-by: Pawel Dembicki <paweldembicki at gmail.com>
+Tested-by: Lech Perczak <lech.perczak at gmail.com>
+Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca/qca8k-8xxx.c | 20 ++++++++------------
+ include/linux/dsa/tag_qca.h      |  2 +-
+ 2 files changed, 9 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
+index 644338ca0510..c5c3b4e92f28 100644
+--- a/drivers/net/dsa/qca/qca8k-8xxx.c
++++ b/drivers/net/dsa/qca/qca8k-8xxx.c
+@@ -1518,9 +1518,9 @@ static void qca8k_mib_autocast_handler(struct dsa_switch *ds, struct sk_buff *sk
+ 	struct qca8k_priv *priv = ds->priv;
+ 	const struct qca8k_mib_desc *mib;
+ 	struct mib_ethhdr *mib_ethhdr;
+-	int i, mib_len, offset = 0;
+-	u64 *data;
++	__le32 *data2;
+ 	u8 port;
++	int i;
+ 
+ 	mib_ethhdr = (struct mib_ethhdr *)skb_mac_header(skb);
+ 	mib_eth_data = &priv->mib_eth_data;
+@@ -1532,28 +1532,24 @@ static void qca8k_mib_autocast_handler(struct dsa_switch *ds, struct sk_buff *sk
+ 	if (port != mib_eth_data->req_port)
+ 		goto exit;
+ 
+-	data = mib_eth_data->data;
++	data2 = (__le32 *)skb->data;
+ 
+ 	for (i = 0; i < priv->info->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];
++			mib_eth_data->data[i] = get_unaligned_le32(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);
++			mib_eth_data->data[i] = get_unaligned_le64((__le64 *)data2);
++		else
++			mib_eth_data->data[i] = get_unaligned_le32(data2);
+ 
+-		/* Set the offset for the next mib */
+-		offset += mib_len;
++		data2 += mib->size;
+ 	}
+ 
+ exit:
+diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h
+index 0e176da1e43f..b1b5720d89a5 100644
+--- a/include/linux/dsa/tag_qca.h
++++ b/include/linux/dsa/tag_qca.h
+@@ -73,7 +73,7 @@ enum mdio_cmd {
+ };
+ 
+ struct mib_ethhdr {
+-	u32 data[3];		/* first 3 mib counter */
++	__le32 data[3];		/* first 3 mib counter */
+ 	__be16 hdr;		/* qca hdr */
+ } __packed;
+ 
+-- 
+2.37.2
+




More information about the lede-commits mailing list