]> git.droids-corp.org - dpdk.git/commitdiff
net/i40e: fix stats counters
authorIgor Ryzhov <iryzhov@nfware.com>
Tue, 17 Nov 2020 08:56:39 +0000 (11:56 +0300)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 8 Jan 2021 15:03:05 +0000 (16:03 +0100)
When low and high registers are read separately, this opens the door to
a race condition:
- low register is read
- NIC updates the registers
- high register is read

Because of this, we may end up with an incorrect counter value.
Let's read the registers in one shot, as it is done in Linux kernel
since the introduction of the i40e driver.

Fixes: 4861cde46116 ("i40e: new poll mode driver")
Cc: stable@dpdk.org
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
drivers/net/i40e/base/i40e_osdep.h
drivers/net/i40e/i40e_ethdev.c

index 9b5033024f77aa6bf312ba92dc41bbae98041297..c9287ff255d5e70710657e0de47371b221bf4a16 100644 (file)
@@ -133,6 +133,14 @@ static inline uint32_t i40e_read_addr(volatile void *addr)
        return rte_le_to_cpu_32(I40E_PCI_REG(addr));
 }
 
+#define I40E_PCI_REG64(reg)            rte_read64(reg)
+#define I40E_PCI_REG64_ADDR(a, reg) \
+       ((volatile uint64_t *)((char *)(a)->hw_addr + (reg)))
+static inline uint64_t i40e_read64_addr(volatile void *addr)
+{
+       return rte_le_to_cpu_64(I40E_PCI_REG64(addr));
+}
+
 #define I40E_PCI_REG_WRITE(reg, value)         \
        rte_write32((rte_cpu_to_le_32(value)), reg)
 #define I40E_PCI_REG_WRITE_RELAXED(reg, value) \
@@ -150,6 +158,8 @@ static inline uint32_t i40e_read_addr(volatile void *addr)
 #define I40E_WRITE_REG(hw, reg, value) \
        I40E_PCI_REG_WRITE(I40E_PCI_REG_ADDR((hw), (reg)), (value))
 
+#define I40E_READ_REG64(hw, reg) i40e_read64_addr(I40E_PCI_REG64_ADDR((hw), (reg)))
+
 #define rd32(a, reg) i40e_read_addr(I40E_PCI_REG_ADDR((a), (reg)))
 #define wr32(a, reg, value) \
        I40E_PCI_REG_WRITE(I40E_PCI_REG_ADDR((a), (reg)), (value))
index 2cb18ecc03593e828081c6bde6155834b7d47a93..7f9bba40523e6bf5642d25dc6a88f5385cc1d62c 100644 (file)
@@ -6620,9 +6620,13 @@ i40e_stat_update_48(struct i40e_hw *hw,
 {
        uint64_t new_data;
 
-       new_data = (uint64_t)I40E_READ_REG(hw, loreg);
-       new_data |= ((uint64_t)(I40E_READ_REG(hw, hireg) &
-                       I40E_16_BIT_MASK)) << I40E_32_BIT_WIDTH;
+       if (hw->device_id == I40E_DEV_ID_QEMU) {
+               new_data = (uint64_t)I40E_READ_REG(hw, loreg);
+               new_data |= ((uint64_t)(I40E_READ_REG(hw, hireg) &
+                               I40E_16_BIT_MASK)) << I40E_32_BIT_WIDTH;
+       } else {
+               new_data = I40E_READ_REG64(hw, loreg);
+       }
 
        if (!offset_loaded)
                *offset = new_data;