net: dsa: qca8k: fix ethtool autocast mib for big-endian systems
authorChristian Marangi <ansuelsmth@gmail.com>
Wed, 12 Oct 2022 17:18:37 +0000 (19:18 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 14 Oct 2022 07:22:28 +0000 (08:22 +0100)
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@gmail.com>
Tested-by: Lech Perczak <lech.perczak@gmail.com>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/qca/qca8k-8xxx.c
include/linux/dsa/tag_qca.h

index 644338ca0510a4f6a50a5e4bc8a861a33f8eaddb..c5c3b4e92f28bf6f0a1a2660b4109f7a22b950b8 100644 (file)
@@ -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:
index 0e176da1e43f438b02bf8a23ceda75989caef3e7..b1b5720d89a596d12eb5cbe9591d0e9e3c5bf918 100644 (file)
@@ -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;