diff options
author | Jack Morgenstein <jackm@dev.mellanox.co.il> | 2012-11-27 11:24:30 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2012-11-29 15:14:54 -0500 |
commit | 311f813a2daefcba03f706a692fe0c67888d7622 (patch) | |
tree | ab2b5e480aa0a8cd35d7e63a1346f89b10009c0b /drivers/net/ethernet/mellanox/mlx4/cmd.c | |
parent | ceb7decb366591e9b67d70832e07f5d240572a3d (diff) |
mlx4_core: Fix potential deadlock in mlx4_eq_int()
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>
Cc: <stable@vger.kernel.org>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/cmd.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/cmd.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index e791e705f7b1..fdc5f23d8e9f 100644 --- 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 mlx4_dev *dev, int slave, u8 cmd, | |||
1498 | u32 reply; | 1498 | u32 reply; |
1499 | u8 is_going_down = 0; | 1499 | u8 is_going_down = 0; |
1500 | int i; | 1500 | int i; |
1501 | unsigned long flags; | ||
1501 | 1502 | ||
1502 | slave_state[slave].comm_toggle ^= 1; | 1503 | slave_state[slave].comm_toggle ^= 1; |
1503 | reply = (u32) slave_state[slave].comm_toggle << 31; | 1504 | reply = (u32) slave_state[slave].comm_toggle << 31; |
@@ -1576,12 +1577,12 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, | |||
1576 | mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave); | 1577 | mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave); |
1577 | goto reset_slave; | 1578 | goto reset_slave; |
1578 | } | 1579 | } |
1579 | spin_lock(&priv->mfunc.master.slave_state_lock); | 1580 | spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); |
1580 | if (!slave_state[slave].is_slave_going_down) | 1581 | if (!slave_state[slave].is_slave_going_down) |
1581 | slave_state[slave].last_cmd = cmd; | 1582 | slave_state[slave].last_cmd = cmd; |
1582 | else | 1583 | else |
1583 | is_going_down = 1; | 1584 | is_going_down = 1; |
1584 | spin_unlock(&priv->mfunc.master.slave_state_lock); | 1585 | spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); |
1585 | if (is_going_down) { | 1586 | if (is_going_down) { |
1586 | mlx4_warn(dev, "Slave is going down aborting command(%d)" | 1587 | mlx4_warn(dev, "Slave is going down aborting command(%d)" |
1587 | " executing from slave:%d\n", | 1588 | " executing from slave:%d\n", |
@@ -1597,10 +1598,10 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, | |||
1597 | reset_slave: | 1598 | reset_slave: |
1598 | /* cleanup any slave resources */ | 1599 | /* cleanup any slave resources */ |
1599 | mlx4_delete_all_resources_for_slave(dev, slave); | 1600 | mlx4_delete_all_resources_for_slave(dev, slave); |
1600 | spin_lock(&priv->mfunc.master.slave_state_lock); | 1601 | spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); |
1601 | if (!slave_state[slave].is_slave_going_down) | 1602 | if (!slave_state[slave].is_slave_going_down) |
1602 | slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET; | 1603 | slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET; |
1603 | spin_unlock(&priv->mfunc.master.slave_state_lock); | 1604 | spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); |
1604 | /*with slave in the middle of flr, no need to clean resources again.*/ | 1605 | /*with slave in the middle of flr, no need to clean resources again.*/ |
1605 | inform_slave_state: | 1606 | inform_slave_state: |
1606 | memset(&slave_state[slave].event_eq, 0, | 1607 | memset(&slave_state[slave].event_eq, 0, |