svn commit: r341566 - in head/sys/dev/mlx5: . mlx5_core
Slava Shwartsman
slavash at FreeBSD.org
Wed Dec 5 13:46:41 UTC 2018
Author: slavash
Date: Wed Dec 5 13:46:39 2018
New Revision: 341566
URL: https://svnweb.freebsd.org/changeset/base/341566
Log:
mlx5: Fixes to allow command polling mode to exist alongside event mode.
A command is either polling or event driven and the mode cannot change
during execution of a command. Make sure the event handler only handle
commands which are not polled. This is done by checking the command mode
in the command handler before completing commands.
Submitted by: hselasky@
Approved by: hselasky (mentor)
MFC after: 1 week
Sponsored by: Mellanox Technologies
Modified:
head/sys/dev/mlx5/driver.h
head/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
head/sys/dev/mlx5/mlx5_core/mlx5_eq.c
head/sys/dev/mlx5/mlx5_core/mlx5_health.c
Modified: head/sys/dev/mlx5/driver.h
==============================================================================
--- head/sys/dev/mlx5/driver.h Wed Dec 5 13:46:09 2018 (r341565)
+++ head/sys/dev/mlx5/driver.h Wed Dec 5 13:46:39 2018 (r341566)
@@ -327,6 +327,11 @@ struct mlx5_traffic_counter {
u64 octets;
};
+enum mlx5_cmd_mode {
+ MLX5_CMD_MODE_POLLING,
+ MLX5_CMD_MODE_EVENTS
+};
+
struct mlx5_cmd_stats {
u64 sum;
u64 n;
@@ -370,8 +375,9 @@ struct mlx5_cmd {
struct workqueue_struct *wq;
struct semaphore sem;
struct semaphore pages_sem;
- int mode;
- struct mlx5_cmd_work_ent *ent_arr[MLX5_MAX_COMMANDS];
+ enum mlx5_cmd_mode mode;
+ struct mlx5_cmd_work_ent * volatile ent_arr[MLX5_MAX_COMMANDS];
+ volatile enum mlx5_cmd_mode ent_mode[MLX5_MAX_COMMANDS];
struct mlx5_cmd_debug dbg;
struct cmd_msg_cache cache;
int checksum_disabled;
@@ -984,7 +990,7 @@ void mlx5_cq_completion(struct mlx5_core_dev *dev, u32
void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type);
void mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type);
struct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn);
-void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vector);
+void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vector, enum mlx5_cmd_mode mode);
void mlx5_cq_event(struct mlx5_core_dev *dev, u32 cqn, int event_type);
int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
int nent, u64 mask, const char *name, struct mlx5_uar *uar);
Modified: head/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
==============================================================================
--- head/sys/dev/mlx5/mlx5_core/mlx5_cmd.c Wed Dec 5 13:46:09 2018 (r341565)
+++ head/sys/dev/mlx5/mlx5_core/mlx5_cmd.c Wed Dec 5 13:46:39 2018 (r341566)
@@ -50,11 +50,6 @@ enum {
};
enum {
- CMD_MODE_POLLING,
- CMD_MODE_EVENTS
-};
-
-enum {
NUM_LONG_LISTS = 2,
NUM_MED_LISTS = 64,
LONG_LIST_SIZE = (2ULL * 1024 * 1024 * 1024 / PAGE_SIZE) * 8 + 16 +
@@ -160,6 +155,8 @@ static int alloc_ent(struct mlx5_cmd_work_ent *ent)
ent->busy = 1;
ent->idx = ret;
clear_bit(ent->idx, &cmd->bitmask);
+ cmd->ent_mode[ent->idx] =
+ ent->polling ? MLX5_CMD_MODE_POLLING : MLX5_CMD_MODE_EVENTS;
cmd->ent_arr[ent->idx] = ent;
}
spin_unlock_irqrestore(&cmd->alloc_lock, flags);
@@ -172,6 +169,8 @@ static void free_ent(struct mlx5_cmd *cmd, int idx)
unsigned long flags;
spin_lock_irqsave(&cmd->alloc_lock, flags);
+ cmd->ent_arr[idx] = NULL; /* safety clear */
+ cmd->ent_mode[idx] = MLX5_CMD_MODE_POLLING; /* reset mode */
set_bit(idx, &cmd->bitmask);
spin_unlock_irqrestore(&cmd->alloc_lock, flags);
}
@@ -786,7 +785,7 @@ static void cb_timeout_handler(struct work_struct *wor
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);
+ mlx5_cmd_comp_handler(dev, 1UL << ent->idx, MLX5_CMD_MODE_EVENTS);
}
static void complete_command(struct mlx5_cmd_work_ent *ent)
@@ -897,11 +896,12 @@ static void cmd_work_handler(struct work_struct *work)
mlx5_fwp_flush(cmd->cmd_page);
iowrite32be(1 << ent->idx, &dev->iseg->cmd_dbell);
mmiowb();
- /* if not in polling don't use ent after this point*/
- if (cmd->mode == CMD_MODE_POLLING || poll_cmd) {
+
+ /* if not in polling don't use ent after this point */
+ if (poll_cmd) {
poll_timeout(ent);
/* make sure we read the descriptor after ownership is SW */
- mlx5_cmd_comp_handler(dev, 1U << ent->idx);
+ mlx5_cmd_comp_handler(dev, 1U << ent->idx, MLX5_CMD_MODE_POLLING);
}
}
@@ -938,15 +938,13 @@ static const char *deliv_status_to_str(u8 status)
static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
{
int timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_MSEC);
- struct mlx5_cmd *cmd = &dev->cmd;
int err;
- if (cmd->mode == CMD_MODE_POLLING || ent->polling) {
+ if (ent->polling) {
wait_for_completion(&ent->done);
- err = ent->ret;
} else if (!wait_for_completion_timeout(&ent->done, timeout)) {
ent->ret = -ETIMEDOUT;
- mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
+ mlx5_cmd_comp_handler(dev, 1UL << ent->idx, MLX5_CMD_MODE_EVENTS);
}
err = ent->ret;
@@ -988,7 +986,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev,
if (IS_ERR(ent))
return PTR_ERR(ent);
- ent->polling = force_polling;
+ ent->polling = force_polling || (cmd->mode == MLX5_CMD_MODE_POLLING);
if (!callback)
init_completion(&ent->done);
@@ -1158,12 +1156,12 @@ static void mlx5_cmd_change_mod(struct mlx5_core_dev *
void mlx5_cmd_use_events(struct mlx5_core_dev *dev)
{
- mlx5_cmd_change_mod(dev, CMD_MODE_EVENTS);
+ mlx5_cmd_change_mod(dev, MLX5_CMD_MODE_EVENTS);
}
void mlx5_cmd_use_polling(struct mlx5_core_dev *dev)
{
- mlx5_cmd_change_mod(dev, CMD_MODE_POLLING);
+ mlx5_cmd_change_mod(dev, MLX5_CMD_MODE_POLLING);
}
static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg)
@@ -1179,7 +1177,8 @@ static void free_msg(struct mlx5_core_dev *dev, struct
}
}
-void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vector_flags)
+void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vector_flags,
+ enum mlx5_cmd_mode cmd_mode)
{
struct mlx5_cmd *cmd = &dev->cmd;
struct mlx5_cmd_work_ent *ent;
@@ -1193,7 +1192,13 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev,
while (vector != 0) {
i = ffs(vector) - 1;
vector &= ~(1U << i);
+ /* check command mode */
+ if (cmd->ent_mode[i] != cmd_mode)
+ continue;
ent = cmd->ent_arr[i];
+ /* check if command was already handled */
+ if (ent == NULL)
+ continue;
if (ent->callback)
cancel_delayed_work(&ent->cb_timeout_work);
ent->ts2 = ktime_get_ns();
@@ -1545,7 +1550,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
mlx5_core_dbg(dev, "descriptor at dma 0x%llx\n", (unsigned long long)(cmd->dma));
- cmd->mode = CMD_MODE_POLLING;
+ cmd->mode = MLX5_CMD_MODE_POLLING;
err = create_msg_cache(dev);
if (err) {
Modified: head/sys/dev/mlx5/mlx5_core/mlx5_eq.c
==============================================================================
--- head/sys/dev/mlx5/mlx5_core/mlx5_eq.c Wed Dec 5 13:46:09 2018 (r341565)
+++ head/sys/dev/mlx5/mlx5_core/mlx5_eq.c Wed Dec 5 13:46:39 2018 (r341566)
@@ -254,8 +254,10 @@ static int mlx5_eq_int(struct mlx5_core_dev *dev, stru
break;
case MLX5_EVENT_TYPE_CMD:
- if (dev->state != MLX5_DEVICE_STATE_INTERNAL_ERROR)
- mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector));
+ if (dev->state != MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+ mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector),
+ MLX5_CMD_MODE_EVENTS);
+ }
break;
case MLX5_EVENT_TYPE_PORT_CHANGE:
Modified: head/sys/dev/mlx5/mlx5_core/mlx5_health.c
==============================================================================
--- head/sys/dev/mlx5/mlx5_core/mlx5_health.c Wed Dec 5 13:46:09 2018 (r341565)
+++ head/sys/dev/mlx5/mlx5_core/mlx5_health.c Wed Dec 5 13:46:39 2018 (r341566)
@@ -141,7 +141,7 @@ static void mlx5_trigger_cmd_completions(struct mlx5_c
spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
mlx5_core_dbg(dev, "vector 0x%jx\n", (uintmax_t)vector);
- mlx5_cmd_comp_handler(dev, vector);
+ mlx5_cmd_comp_handler(dev, vector, MLX5_CMD_MODE_EVENTS);
return;
no_trig:
More information about the svn-src-all
mailing list