]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
bnxt_en: Fix ethtool -d byte order for 32-bit values
authorMichael Chan <michael.chan@broadcom.com>
Mon, 28 Apr 2025 22:59:03 +0000 (15:59 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 4 Jun 2025 12:36:52 +0000 (14:36 +0200)
[ Upstream commit 02e8be5a032cae0f4ca33c6053c44d83cf4acc93 ]

For version 1 register dump that includes the PCIe stats, the existing
code incorrectly assumes that all PCIe stats are 64-bit values.  Fix it
by using an array containing the starting and ending index of the 32-bit
values.  The loop in bnxt_get_regs() will use the array to do proper
endian swap for the 32-bit values.

Fixes: b5d600b027eb ("bnxt_en: Add support for 'ethtool -d'")
Reviewed-by: Shruti Parab <shruti.parab@broadcom.com>
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

index 2984234df67eb3950714d2e9bcf65714c42f3dcc..4dfb65b0bf1c6c1b6cff6c20e1f5ae612a3e0598 100644 (file)
@@ -1344,6 +1344,17 @@ static int bnxt_get_regs_len(struct net_device *dev)
        return reg_len;
 }
 
+#define BNXT_PCIE_32B_ENTRY(start, end)                        \
+        { offsetof(struct pcie_ctx_hw_stats, start),   \
+          offsetof(struct pcie_ctx_hw_stats, end) }
+
+static const struct {
+       u16 start;
+       u16 end;
+} bnxt_pcie_32b_entries[] = {
+       BNXT_PCIE_32B_ENTRY(pcie_ltssm_histogram[0], pcie_ltssm_histogram[3]),
+};
+
 static void bnxt_get_regs(struct net_device *dev, struct ethtool_regs *regs,
                          void *_p)
 {
@@ -1372,12 +1383,27 @@ static void bnxt_get_regs(struct net_device *dev, struct ethtool_regs *regs,
        mutex_lock(&bp->hwrm_cmd_lock);
        rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (!rc) {
-               __le64 *src = (__le64 *)hw_pcie_stats;
-               u64 *dst = (u64 *)(_p + BNXT_PXP_REG_LEN);
-               int i;
+               u8 *dst = (u8 *)(_p + BNXT_PXP_REG_LEN);
+               u8 *src = (u8 *)hw_pcie_stats;
+               int i, j;
+
+               for (i = 0, j = 0; i < sizeof(*hw_pcie_stats); ) {
+                       if (i >= bnxt_pcie_32b_entries[j].start &&
+                           i <= bnxt_pcie_32b_entries[j].end) {
+                               u32 *dst32 = (u32 *)(dst + i);
+
+                               *dst32 = le32_to_cpu(*(__le32 *)(src + i));
+                               i += 4;
+                               if (i > bnxt_pcie_32b_entries[j].end &&
+                                   j < ARRAY_SIZE(bnxt_pcie_32b_entries) - 1)
+                                       j++;
+                       } else {
+                               u64 *dst64 = (u64 *)(dst + i);
 
-               for (i = 0; i < sizeof(*hw_pcie_stats) / sizeof(__le64); i++)
-                       dst[i] = le64_to_cpu(src[i]);
+                               *dst64 = le64_to_cpu(*(__le64 *)(src + i));
+                               i += 8;
+                       }
+               }
        }
        mutex_unlock(&bp->hwrm_cmd_lock);
        dma_free_coherent(&bp->pdev->dev, sizeof(*hw_pcie_stats), hw_pcie_stats,