net/mlx4: Copy/set only sizeof struct mlx4_eqe bytes
authorCarol L Soto <clsoto@linux.vnet.ibm.com>
Tue, 27 Oct 2015 15:36:20 +0000 (17:36 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Dec 2015 18:40:06 +0000 (13:40 -0500)
[ Upstream commit c02b05011fadf8e409e41910217ca689f2fc9d91 ]

When doing memcpy/memset of EQEs, we should use sizeof struct
mlx4_eqe as the base size and not caps.eqe_size which could be bigger.

If caps.eqe_size is bigger than the struct mlx4_eqe then we corrupt
data in the master context.

When using a 64 byte stride, the memcpy copied over 63 bytes to the
slave_eq structure.  This resulted in copying over the entire eqe of
interest, including its ownership bit -- and also 31 bytes of garbage
into the next WQE in the slave EQ -- which did NOT include the ownership
bit (and therefore had no impact).

However, once the stride is increased to 128, we are overwriting the
ownership bits of *three* eqes in the slave_eq struct.  This results
in an incorrect ownership bit for those eqes, which causes the eq to
seem to be full. The issue therefore surfaced only once 128-byte EQEs
started being used in SRIOV and (overarchitectures that have 128/256
byte cache-lines such as PPC) - e.g after commit 77507aa249ae
"net/mlx4_core: Enable CQE/EQE stride support".

Fixes: 08ff32352d6f ('mlx4: 64-byte CQE/EQE support')
Signed-off-by: Carol L Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/eq.c

index 28d706bd12ebb6b5d588e8c2de9a932e62dfc038..d64050fcafc389a9b9dd40309f5e1a8c7c5ec691 100644 (file)
@@ -1836,7 +1836,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
                        spin_lock_init(&s_state->lock);
                }
 
-               memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size);
+               memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe));
                priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD;
                INIT_WORK(&priv->mfunc.master.comm_work,
                          mlx4_master_comm_channel);
index 6000342f9725db0f29e8bac3a249765e53c90173..16a1ccc269f1b68cf7c812eb12e1a87cd24a68c5 100644 (file)
@@ -183,7 +183,7 @@ static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe)
                return;
        }
 
-       memcpy(s_eqe, eqe, dev->caps.eqe_size - 1);
+       memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1);
        s_eqe->slave_id = slave;
        /* ensure all information is written before setting the ownersip bit */
        wmb();