93c0bb85b5bc955e1e31d6881070005adf94fac7
[openwrt/staging/mans0n.git] /
1 From 0d4636f7d72df3179b20a2d32b647881917a5e2a Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Wed, 12 Oct 2022 19:18:37 +0200
4 Subject: [PATCH 2/2] net: dsa: qca8k: fix ethtool autocast mib for big-endian
5 systems
6
7 The switch sends autocast mib in little-endian. This is problematic for
8 big-endian system as the values needs to be converted.
9
10 Fix this by converting each mib value to cpu byte order.
11
12 Fixes: 5c957c7ca78c ("net: dsa: qca8k: add support for mib autocast in Ethernet packet")
13 Tested-by: Pawel Dembicki <paweldembicki@gmail.com>
14 Tested-by: Lech Perczak <lech.perczak@gmail.com>
15 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
16 Signed-off-by: David S. Miller <davem@davemloft.net>
17 ---
18 drivers/net/dsa/qca/qca8k-8xxx.c | 20 ++++++++------------
19 include/linux/dsa/tag_qca.h | 2 +-
20 2 files changed, 9 insertions(+), 13 deletions(-)
21
22 diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
23 index 644338ca0510..c5c3b4e92f28 100644
24 --- a/drivers/net/dsa/qca/qca8k-8xxx.c
25 +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
26 @@ -1518,9 +1518,9 @@ static void qca8k_mib_autocast_handler(struct dsa_switch *ds, struct sk_buff *sk
27 struct qca8k_priv *priv = ds->priv;
28 const struct qca8k_mib_desc *mib;
29 struct mib_ethhdr *mib_ethhdr;
30 - int i, mib_len, offset = 0;
31 - u64 *data;
32 + __le32 *data2;
33 u8 port;
34 + int i;
35
36 mib_ethhdr = (struct mib_ethhdr *)skb_mac_header(skb);
37 mib_eth_data = &priv->mib_eth_data;
38 @@ -1532,28 +1532,24 @@ static void qca8k_mib_autocast_handler(struct dsa_switch *ds, struct sk_buff *sk
39 if (port != mib_eth_data->req_port)
40 goto exit;
41
42 - data = mib_eth_data->data;
43 + data2 = (__le32 *)skb->data;
44
45 for (i = 0; i < priv->info->mib_count; i++) {
46 mib = &ar8327_mib[i];
47
48 /* First 3 mib are present in the skb head */
49 if (i < 3) {
50 - data[i] = mib_ethhdr->data[i];
51 + mib_eth_data->data[i] = get_unaligned_le32(mib_ethhdr->data + i);
52 continue;
53 }
54
55 - mib_len = sizeof(uint32_t);
56 -
57 /* Some mib are 64 bit wide */
58 if (mib->size == 2)
59 - mib_len = sizeof(uint64_t);
60 -
61 - /* Copy the mib value from packet to the */
62 - memcpy(data + i, skb->data + offset, mib_len);
63 + mib_eth_data->data[i] = get_unaligned_le64((__le64 *)data2);
64 + else
65 + mib_eth_data->data[i] = get_unaligned_le32(data2);
66
67 - /* Set the offset for the next mib */
68 - offset += mib_len;
69 + data2 += mib->size;
70 }
71
72 exit:
73 diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h
74 index 0e176da1e43f..b1b5720d89a5 100644
75 --- a/include/linux/dsa/tag_qca.h
76 +++ b/include/linux/dsa/tag_qca.h
77 @@ -73,7 +73,7 @@ enum mdio_cmd {
78 };
79
80 struct mib_ethhdr {
81 - u32 data[3]; /* first 3 mib counter */
82 + __le32 data[3]; /* first 3 mib counter */
83 __be16 hdr; /* qca hdr */
84 } __packed;
85
86 --
87 2.37.2
88