aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2012-11-27 11:24:30 -0500
committerRoland Dreier <roland@purestorage.com>2012-11-29 15:14:54 -0500
commit311f813a2daefcba03f706a692fe0c67888d7622 (patch)
treeab2b5e480aa0a8cd35d7e63a1346f89b10009c0b
parentceb7decb366591e9b67d70832e07f5d240572a3d (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>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/eq.c10
2 files changed, 11 insertions, 8 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,
1597reset_slave: 1598reset_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.*/
1605inform_slave_state: 1606inform_slave_state:
1606 memset(&slave_state[slave].event_eq, 0, 1607 memset(&slave_state[slave].event_eq, 0,
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index c509a86db610..3cb7727408e5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -407,6 +407,7 @@ void mlx4_master_handle_slave_flr(struct work_struct *work)
407 struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; 407 struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
408 int i; 408 int i;
409 int err; 409 int err;
410 unsigned long flags;
410 411
411 mlx4_dbg(dev, "mlx4_handle_slave_flr\n"); 412 mlx4_dbg(dev, "mlx4_handle_slave_flr\n");
412 413
@@ -418,10 +419,10 @@ void mlx4_master_handle_slave_flr(struct work_struct *work)
418 419
419 mlx4_delete_all_resources_for_slave(dev, i); 420 mlx4_delete_all_resources_for_slave(dev, i);
420 /*return the slave to running mode*/ 421 /*return the slave to running mode*/
421 spin_lock(&priv->mfunc.master.slave_state_lock); 422 spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
422 slave_state[i].last_cmd = MLX4_COMM_CMD_RESET; 423 slave_state[i].last_cmd = MLX4_COMM_CMD_RESET;
423 slave_state[i].is_slave_going_down = 0; 424 slave_state[i].is_slave_going_down = 0;
424 spin_unlock(&priv->mfunc.master.slave_state_lock); 425 spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
425 /*notify the FW:*/ 426 /*notify the FW:*/
426 err = mlx4_cmd(dev, 0, i, 0, MLX4_CMD_INFORM_FLR_DONE, 427 err = mlx4_cmd(dev, 0, i, 0, MLX4_CMD_INFORM_FLR_DONE,
427 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 428 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
@@ -446,6 +447,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
446 u8 update_slave_state; 447 u8 update_slave_state;
447 int i; 448 int i;
448 enum slave_port_gen_event gen_event; 449 enum slave_port_gen_event gen_event;
450 unsigned long flags;
449 451
450 while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor))) { 452 while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor))) {
451 /* 453 /*
@@ -653,13 +655,13 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
653 } else 655 } else
654 update_slave_state = 1; 656 update_slave_state = 1;
655 657
656 spin_lock(&priv->mfunc.master.slave_state_lock); 658 spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
657 if (update_slave_state) { 659 if (update_slave_state) {
658 priv->mfunc.master.slave_state[flr_slave].active = false; 660 priv->mfunc.master.slave_state[flr_slave].active = false;
659 priv->mfunc.master.slave_state[flr_slave].last_cmd = MLX4_COMM_CMD_FLR; 661 priv->mfunc.master.slave_state[flr_slave].last_cmd = MLX4_COMM_CMD_FLR;
660 priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1; 662 priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1;
661 } 663 }
662 spin_unlock(&priv->mfunc.master.slave_state_lock); 664 spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
663 queue_work(priv->mfunc.master.comm_wq, 665 queue_work(priv->mfunc.master.comm_wq,
664 &priv->mfunc.master.slave_flr_event_work); 666 &priv->mfunc.master.slave_flr_event_work);
665 break; 667 break;