|
@@ -606,11 +606,36 @@ static void dump_command(struct mlx5_core_dev *dev,
|
|
|
pr_debug("\n");
|
|
|
}
|
|
|
|
|
|
+static u16 msg_to_opcode(struct mlx5_cmd_msg *in)
|
|
|
+{
|
|
|
+ struct mlx5_inbox_hdr *hdr = (struct mlx5_inbox_hdr *)(in->first.data);
|
|
|
+
|
|
|
+ return be16_to_cpu(hdr->opcode);
|
|
|
+}
|
|
|
+
|
|
|
+static void cb_timeout_handler(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct delayed_work *dwork = container_of(work, struct delayed_work,
|
|
|
+ work);
|
|
|
+ struct mlx5_cmd_work_ent *ent = container_of(dwork,
|
|
|
+ struct mlx5_cmd_work_ent,
|
|
|
+ cb_timeout_work);
|
|
|
+ struct mlx5_core_dev *dev = container_of(ent->cmd, struct mlx5_core_dev,
|
|
|
+ cmd);
|
|
|
+
|
|
|
+ ent->ret = -ETIMEDOUT;
|
|
|
+ mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",
|
|
|
+ mlx5_command_str(msg_to_opcode(ent->in)),
|
|
|
+ msg_to_opcode(ent->in));
|
|
|
+ mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
|
|
|
+}
|
|
|
+
|
|
|
static void cmd_work_handler(struct work_struct *work)
|
|
|
{
|
|
|
struct mlx5_cmd_work_ent *ent = container_of(work, struct mlx5_cmd_work_ent, work);
|
|
|
struct mlx5_cmd *cmd = ent->cmd;
|
|
|
struct mlx5_core_dev *dev = container_of(cmd, struct mlx5_core_dev, cmd);
|
|
|
+ unsigned long cb_timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_MSEC);
|
|
|
struct mlx5_cmd_layout *lay;
|
|
|
struct semaphore *sem;
|
|
|
unsigned long flags;
|
|
@@ -651,6 +676,9 @@ static void cmd_work_handler(struct work_struct *work)
|
|
|
dump_command(dev, ent, 1);
|
|
|
ent->ts1 = ktime_get_ns();
|
|
|
|
|
|
+ if (ent->callback)
|
|
|
+ schedule_delayed_work(&ent->cb_timeout_work, cb_timeout);
|
|
|
+
|
|
|
/* ring doorbell after the descriptor is valid */
|
|
|
mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx);
|
|
|
wmb();
|
|
@@ -695,13 +723,6 @@ static const char *deliv_status_to_str(u8 status)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static u16 msg_to_opcode(struct mlx5_cmd_msg *in)
|
|
|
-{
|
|
|
- struct mlx5_inbox_hdr *hdr = (struct mlx5_inbox_hdr *)(in->first.data);
|
|
|
-
|
|
|
- return be16_to_cpu(hdr->opcode);
|
|
|
-}
|
|
|
-
|
|
|
static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
|
|
|
{
|
|
|
unsigned long timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_MSEC);
|
|
@@ -765,6 +786,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
|
|
|
if (!callback)
|
|
|
init_completion(&ent->done);
|
|
|
|
|
|
+ INIT_DELAYED_WORK(&ent->cb_timeout_work, cb_timeout_handler);
|
|
|
INIT_WORK(&ent->work, cmd_work_handler);
|
|
|
if (page_queue) {
|
|
|
cmd_work_handler(&ent->work);
|
|
@@ -1242,6 +1264,8 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)
|
|
|
struct semaphore *sem;
|
|
|
|
|
|
ent = cmd->ent_arr[i];
|
|
|
+ if (ent->callback)
|
|
|
+ cancel_delayed_work(&ent->cb_timeout_work);
|
|
|
if (ent->page_queue)
|
|
|
sem = &cmd->pages_sem;
|
|
|
else
|