lkml.org 
[lkml]   [2013]   [Jan]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[ 044/221] mlx4_core: Fix potential deadlock in mlx4_eq_int()
    Date
    3.7-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Jack Morgenstein <jackm@dev.mellanox.co.il>

    commit 311f813a2daefcba03f706a692fe0c67888d7622 upstream.

    The slave_state_lock spinlock is used in both interrupt context and
    process context, hence irq locking must be used. Found by lockdep.

    Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
    Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
    Signed-off-by: Roland Dreier <roland@purestorage.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/net/ethernet/mellanox/mlx4/cmd.c | 9 +++++----
    drivers/net/ethernet/mellanox/mlx4/eq.c | 10 ++++++----
    2 files changed, 11 insertions(+), 8 deletions(-)

    --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
    +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
    @@ -1498,6 +1498,7 @@ static void mlx4_master_do_cmd(struct ml
    u32 reply;
    u8 is_going_down = 0;
    int i;
    + unsigned long flags;

    slave_state[slave].comm_toggle ^= 1;
    reply = (u32) slave_state[slave].comm_toggle << 31;
    @@ -1576,12 +1577,12 @@ static void mlx4_master_do_cmd(struct ml
    mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave);
    goto reset_slave;
    }
    - spin_lock(&priv->mfunc.master.slave_state_lock);
    + spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
    if (!slave_state[slave].is_slave_going_down)
    slave_state[slave].last_cmd = cmd;
    else
    is_going_down = 1;
    - spin_unlock(&priv->mfunc.master.slave_state_lock);
    + spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
    if (is_going_down) {
    mlx4_warn(dev, "Slave is going down aborting command(%d)"
    " executing from slave:%d\n",
    @@ -1597,10 +1598,10 @@ static void mlx4_master_do_cmd(struct ml
    reset_slave:
    /* cleanup any slave resources */
    mlx4_delete_all_resources_for_slave(dev, slave);
    - spin_lock(&priv->mfunc.master.slave_state_lock);
    + spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
    if (!slave_state[slave].is_slave_going_down)
    slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET;
    - spin_unlock(&priv->mfunc.master.slave_state_lock);
    + spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
    /*with slave in the middle of flr, no need to clean resources again.*/
    inform_slave_state:
    memset(&slave_state[slave].event_eq, 0,
    --- a/drivers/net/ethernet/mellanox/mlx4/eq.c
    +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
    @@ -401,6 +401,7 @@ void mlx4_master_handle_slave_flr(struct
    struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
    int i;
    int err;
    + unsigned long flags;

    mlx4_dbg(dev, "mlx4_handle_slave_flr\n");

    @@ -412,10 +413,10 @@ void mlx4_master_handle_slave_flr(struct

    mlx4_delete_all_resources_for_slave(dev, i);
    /*return the slave to running mode*/
    - spin_lock(&priv->mfunc.master.slave_state_lock);
    + spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
    slave_state[i].last_cmd = MLX4_COMM_CMD_RESET;
    slave_state[i].is_slave_going_down = 0;
    - spin_unlock(&priv->mfunc.master.slave_state_lock);
    + spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
    /*notify the FW:*/
    err = mlx4_cmd(dev, 0, i, 0, MLX4_CMD_INFORM_FLR_DONE,
    MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
    @@ -440,6 +441,7 @@ static int mlx4_eq_int(struct mlx4_dev *
    u8 update_slave_state;
    int i;
    enum slave_port_gen_event gen_event;
    + unsigned long flags;

    while ((eqe = next_eqe_sw(eq))) {
    /*
    @@ -647,13 +649,13 @@ static int mlx4_eq_int(struct mlx4_dev *
    } else
    update_slave_state = 1;

    - spin_lock(&priv->mfunc.master.slave_state_lock);
    + spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
    if (update_slave_state) {
    priv->mfunc.master.slave_state[flr_slave].active = false;
    priv->mfunc.master.slave_state[flr_slave].last_cmd = MLX4_COMM_CMD_FLR;
    priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1;
    }
    - spin_unlock(&priv->mfunc.master.slave_state_lock);
    + spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
    queue_work(priv->mfunc.master.comm_wq,
    &priv->mfunc.master.slave_flr_event_work);
    break;



    \
     
     \ /
      Last update: 2013-01-15 21:01    [W:3.410 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site