net/mlx5: DR, Add support for writing modify header argument
The accelerated modify header arguments are written in the HW area with special WQE and specific data format. New function was added to support writing of new argument type. Note that GTA WQE is larger than READ and WRITE, so the queue management logic was updated to support this. Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com> Reviewed-by: Alex Vesker <valex@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
This commit is contained in:
parent
de69696b6e
commit
4605fc0a2b
|
@ -20,6 +20,7 @@ struct dr_data_seg {
|
||||||
|
|
||||||
enum send_info_type {
|
enum send_info_type {
|
||||||
WRITE_ICM = 0,
|
WRITE_ICM = 0,
|
||||||
|
GTA_ARG = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct postsend_info {
|
struct postsend_info {
|
||||||
|
@ -269,6 +270,7 @@ static struct mlx5dr_qp *dr_create_rc_qp(struct mlx5_core_dev *mdev,
|
||||||
dr_qp->rq.wqe_cnt = 4;
|
dr_qp->rq.wqe_cnt = 4;
|
||||||
dr_qp->sq.pc = 0;
|
dr_qp->sq.pc = 0;
|
||||||
dr_qp->sq.cc = 0;
|
dr_qp->sq.cc = 0;
|
||||||
|
dr_qp->sq.head = 0;
|
||||||
dr_qp->sq.wqe_cnt = roundup_pow_of_two(attr->max_send_wr);
|
dr_qp->sq.wqe_cnt = roundup_pow_of_two(attr->max_send_wr);
|
||||||
|
|
||||||
MLX5_SET(qpc, temp_qpc, log_rq_stride, ilog2(MLX5_SEND_WQE_DS) - 4);
|
MLX5_SET(qpc, temp_qpc, log_rq_stride, ilog2(MLX5_SEND_WQE_DS) - 4);
|
||||||
|
@ -367,39 +369,113 @@ static void dr_cmd_notify_hw(struct mlx5dr_qp *dr_qp, void *ctrl)
|
||||||
mlx5_write64(ctrl, dr_qp->uar->map + MLX5_BF_OFFSET);
|
mlx5_write64(ctrl, dr_qp->uar->map + MLX5_BF_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dr_rdma_segments(struct mlx5dr_qp *dr_qp, u64 remote_addr,
|
static void
|
||||||
u32 rkey, struct dr_data_seg *data_seg,
|
dr_rdma_handle_flow_access_arg_segments(struct mlx5_wqe_ctrl_seg *wq_ctrl,
|
||||||
u32 opcode, bool notify_hw)
|
u32 remote_addr,
|
||||||
|
struct dr_data_seg *data_seg,
|
||||||
|
int *size)
|
||||||
|
{
|
||||||
|
struct mlx5_wqe_header_modify_argument_update_seg *wq_arg_seg;
|
||||||
|
struct mlx5_wqe_flow_update_ctrl_seg *wq_flow_seg;
|
||||||
|
|
||||||
|
wq_ctrl->general_id = cpu_to_be32(remote_addr);
|
||||||
|
wq_flow_seg = (void *)(wq_ctrl + 1);
|
||||||
|
|
||||||
|
/* mlx5_wqe_flow_update_ctrl_seg - all reserved */
|
||||||
|
memset(wq_flow_seg, 0, sizeof(*wq_flow_seg));
|
||||||
|
wq_arg_seg = (void *)(wq_flow_seg + 1);
|
||||||
|
|
||||||
|
memcpy(wq_arg_seg->argument_list,
|
||||||
|
(void *)(uintptr_t)data_seg->addr,
|
||||||
|
data_seg->length);
|
||||||
|
|
||||||
|
*size = (sizeof(*wq_ctrl) + /* WQE ctrl segment */
|
||||||
|
sizeof(*wq_flow_seg) + /* WQE flow update ctrl seg - reserved */
|
||||||
|
sizeof(*wq_arg_seg)) / /* WQE hdr modify arg seg - data */
|
||||||
|
MLX5_SEND_WQE_DS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dr_rdma_handle_icm_write_segments(struct mlx5_wqe_ctrl_seg *wq_ctrl,
|
||||||
|
u64 remote_addr,
|
||||||
|
u32 rkey,
|
||||||
|
struct dr_data_seg *data_seg,
|
||||||
|
unsigned int *size)
|
||||||
{
|
{
|
||||||
struct mlx5_wqe_raddr_seg *wq_raddr;
|
struct mlx5_wqe_raddr_seg *wq_raddr;
|
||||||
struct mlx5_wqe_ctrl_seg *wq_ctrl;
|
|
||||||
struct mlx5_wqe_data_seg *wq_dseg;
|
struct mlx5_wqe_data_seg *wq_dseg;
|
||||||
unsigned int size;
|
|
||||||
unsigned int idx;
|
|
||||||
|
|
||||||
size = sizeof(*wq_ctrl) / 16 + sizeof(*wq_dseg) / 16 +
|
|
||||||
sizeof(*wq_raddr) / 16;
|
|
||||||
|
|
||||||
idx = dr_qp->sq.pc & (dr_qp->sq.wqe_cnt - 1);
|
|
||||||
|
|
||||||
wq_ctrl = mlx5_wq_cyc_get_wqe(&dr_qp->wq.sq, idx);
|
|
||||||
wq_ctrl->imm = 0;
|
|
||||||
wq_ctrl->fm_ce_se = (data_seg->send_flags) ?
|
|
||||||
MLX5_WQE_CTRL_CQ_UPDATE : 0;
|
|
||||||
wq_ctrl->opmod_idx_opcode = cpu_to_be32(((dr_qp->sq.pc & 0xffff) << 8) |
|
|
||||||
opcode);
|
|
||||||
wq_ctrl->qpn_ds = cpu_to_be32(size | dr_qp->qpn << 8);
|
|
||||||
wq_raddr = (void *)(wq_ctrl + 1);
|
wq_raddr = (void *)(wq_ctrl + 1);
|
||||||
|
|
||||||
wq_raddr->raddr = cpu_to_be64(remote_addr);
|
wq_raddr->raddr = cpu_to_be64(remote_addr);
|
||||||
wq_raddr->rkey = cpu_to_be32(rkey);
|
wq_raddr->rkey = cpu_to_be32(rkey);
|
||||||
wq_raddr->reserved = 0;
|
wq_raddr->reserved = 0;
|
||||||
|
|
||||||
wq_dseg = (void *)(wq_raddr + 1);
|
wq_dseg = (void *)(wq_raddr + 1);
|
||||||
|
|
||||||
wq_dseg->byte_count = cpu_to_be32(data_seg->length);
|
wq_dseg->byte_count = cpu_to_be32(data_seg->length);
|
||||||
wq_dseg->lkey = cpu_to_be32(data_seg->lkey);
|
wq_dseg->lkey = cpu_to_be32(data_seg->lkey);
|
||||||
wq_dseg->addr = cpu_to_be64(data_seg->addr);
|
wq_dseg->addr = cpu_to_be64(data_seg->addr);
|
||||||
|
|
||||||
dr_qp->sq.wqe_head[idx] = dr_qp->sq.pc++;
|
*size = (sizeof(*wq_ctrl) + /* WQE ctrl segment */
|
||||||
|
sizeof(*wq_dseg) + /* WQE data segment */
|
||||||
|
sizeof(*wq_raddr)) / /* WQE remote addr segment */
|
||||||
|
MLX5_SEND_WQE_DS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dr_set_ctrl_seg(struct mlx5_wqe_ctrl_seg *wq_ctrl,
|
||||||
|
struct dr_data_seg *data_seg)
|
||||||
|
{
|
||||||
|
wq_ctrl->signature = 0;
|
||||||
|
wq_ctrl->rsvd[0] = 0;
|
||||||
|
wq_ctrl->rsvd[1] = 0;
|
||||||
|
wq_ctrl->fm_ce_se = data_seg->send_flags & IB_SEND_SIGNALED ?
|
||||||
|
MLX5_WQE_CTRL_CQ_UPDATE : 0;
|
||||||
|
wq_ctrl->imm = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dr_rdma_segments(struct mlx5dr_qp *dr_qp, u64 remote_addr,
|
||||||
|
u32 rkey, struct dr_data_seg *data_seg,
|
||||||
|
u32 opcode, bool notify_hw)
|
||||||
|
{
|
||||||
|
struct mlx5_wqe_ctrl_seg *wq_ctrl;
|
||||||
|
int opcode_mod = 0;
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int idx;
|
||||||
|
|
||||||
|
idx = dr_qp->sq.pc & (dr_qp->sq.wqe_cnt - 1);
|
||||||
|
|
||||||
|
wq_ctrl = mlx5_wq_cyc_get_wqe(&dr_qp->wq.sq, idx);
|
||||||
|
dr_set_ctrl_seg(wq_ctrl, data_seg);
|
||||||
|
|
||||||
|
switch (opcode) {
|
||||||
|
case MLX5_OPCODE_RDMA_READ:
|
||||||
|
case MLX5_OPCODE_RDMA_WRITE:
|
||||||
|
dr_rdma_handle_icm_write_segments(wq_ctrl, remote_addr,
|
||||||
|
rkey, data_seg, &size);
|
||||||
|
break;
|
||||||
|
case MLX5_OPCODE_FLOW_TBL_ACCESS:
|
||||||
|
opcode_mod = MLX5_CMD_OP_MOD_UPDATE_HEADER_MODIFY_ARGUMENT;
|
||||||
|
dr_rdma_handle_flow_access_arg_segments(wq_ctrl, remote_addr,
|
||||||
|
data_seg, &size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN(true, "illegal opcode %d", opcode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------
|
||||||
|
* |opcode_mod (8 bit)|wqe_index (16 bits)| opcod (8 bits)|
|
||||||
|
* --------------------------------------------------------
|
||||||
|
*/
|
||||||
|
wq_ctrl->opmod_idx_opcode =
|
||||||
|
cpu_to_be32((opcode_mod << 24) |
|
||||||
|
((dr_qp->sq.pc & 0xffff) << 8) |
|
||||||
|
opcode);
|
||||||
|
wq_ctrl->qpn_ds = cpu_to_be32(size | dr_qp->qpn << 8);
|
||||||
|
|
||||||
|
dr_qp->sq.pc += DIV_ROUND_UP(size * 16, MLX5_SEND_WQE_BB);
|
||||||
|
dr_qp->sq.wqe_head[idx] = dr_qp->sq.head++;
|
||||||
|
|
||||||
if (notify_hw)
|
if (notify_hw)
|
||||||
dr_cmd_notify_hw(dr_qp, wq_ctrl);
|
dr_cmd_notify_hw(dr_qp, wq_ctrl);
|
||||||
|
@ -412,7 +488,11 @@ static void dr_post_send(struct mlx5dr_qp *dr_qp, struct postsend_info *send_inf
|
||||||
&send_info->write, MLX5_OPCODE_RDMA_WRITE, false);
|
&send_info->write, MLX5_OPCODE_RDMA_WRITE, false);
|
||||||
dr_rdma_segments(dr_qp, send_info->remote_addr, send_info->rkey,
|
dr_rdma_segments(dr_qp, send_info->remote_addr, send_info->rkey,
|
||||||
&send_info->read, MLX5_OPCODE_RDMA_READ, true);
|
&send_info->read, MLX5_OPCODE_RDMA_READ, true);
|
||||||
|
} else { /* GTA_ARG */
|
||||||
|
dr_rdma_segments(dr_qp, send_info->remote_addr, send_info->rkey,
|
||||||
|
&send_info->write, MLX5_OPCODE_FLOW_TBL_ACCESS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -478,11 +558,23 @@ static int dr_handle_pending_wc(struct mlx5dr_domain *dmn,
|
||||||
} else if (ne == 1) {
|
} else if (ne == 1) {
|
||||||
send_ring->pending_wqe -= send_ring->signal_th;
|
send_ring->pending_wqe -= send_ring->signal_th;
|
||||||
}
|
}
|
||||||
} while (is_drain && send_ring->pending_wqe);
|
} while (ne == 1 ||
|
||||||
|
(is_drain && send_ring->pending_wqe >= send_ring->signal_th));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dr_fill_write_args_segs(struct mlx5dr_send_ring *send_ring,
|
||||||
|
struct postsend_info *send_info)
|
||||||
|
{
|
||||||
|
send_ring->pending_wqe++;
|
||||||
|
|
||||||
|
if (send_ring->pending_wqe % send_ring->signal_th == 0)
|
||||||
|
send_info->write.send_flags |= IB_SEND_SIGNALED;
|
||||||
|
else
|
||||||
|
send_info->write.send_flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void dr_fill_write_icm_segs(struct mlx5dr_domain *dmn,
|
static void dr_fill_write_icm_segs(struct mlx5dr_domain *dmn,
|
||||||
struct mlx5dr_send_ring *send_ring,
|
struct mlx5dr_send_ring *send_ring,
|
||||||
struct postsend_info *send_info)
|
struct postsend_info *send_info)
|
||||||
|
@ -526,6 +618,8 @@ static void dr_fill_data_segs(struct mlx5dr_domain *dmn,
|
||||||
{
|
{
|
||||||
if (send_info->type == WRITE_ICM)
|
if (send_info->type == WRITE_ICM)
|
||||||
dr_fill_write_icm_segs(dmn, send_ring, send_info);
|
dr_fill_write_icm_segs(dmn, send_ring, send_info);
|
||||||
|
else /* args */
|
||||||
|
dr_fill_write_args_segs(send_ring, send_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dr_postsend_icm_data(struct mlx5dr_domain *dmn,
|
static int dr_postsend_icm_data(struct mlx5dr_domain *dmn,
|
||||||
|
@ -774,6 +868,39 @@ int mlx5dr_send_postsend_pattern(struct mlx5dr_domain *dmn,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mlx5dr_send_postsend_args(struct mlx5dr_domain *dmn, u64 arg_id,
|
||||||
|
u16 num_of_actions, u8 *actions_data)
|
||||||
|
{
|
||||||
|
int data_len, iter = 0, cur_sent;
|
||||||
|
u64 addr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
addr = (uintptr_t)actions_data;
|
||||||
|
data_len = num_of_actions * DR_MODIFY_ACTION_SIZE;
|
||||||
|
|
||||||
|
do {
|
||||||
|
struct postsend_info send_info = {};
|
||||||
|
|
||||||
|
send_info.type = GTA_ARG;
|
||||||
|
send_info.write.addr = addr;
|
||||||
|
cur_sent = min_t(u32, data_len, DR_ACTION_CACHE_LINE_SIZE);
|
||||||
|
send_info.write.length = cur_sent;
|
||||||
|
send_info.write.lkey = 0;
|
||||||
|
send_info.remote_addr = arg_id + iter;
|
||||||
|
|
||||||
|
ret = dr_postsend_icm_data(dmn, &send_info);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
iter++;
|
||||||
|
addr += cur_sent;
|
||||||
|
data_len -= cur_sent;
|
||||||
|
} while (data_len > 0);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int dr_modify_qp_rst2init(struct mlx5_core_dev *mdev,
|
static int dr_modify_qp_rst2init(struct mlx5_core_dev *mdev,
|
||||||
struct mlx5dr_qp *dr_qp,
|
struct mlx5dr_qp *dr_qp,
|
||||||
int port)
|
int port)
|
||||||
|
|
|
@ -1397,6 +1397,7 @@ struct mlx5dr_qp {
|
||||||
struct mlx5_wq_ctrl wq_ctrl;
|
struct mlx5_wq_ctrl wq_ctrl;
|
||||||
u32 qpn;
|
u32 qpn;
|
||||||
struct {
|
struct {
|
||||||
|
unsigned int head;
|
||||||
unsigned int pc;
|
unsigned int pc;
|
||||||
unsigned int cc;
|
unsigned int cc;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
@ -1473,6 +1474,8 @@ int mlx5dr_send_postsend_pattern(struct mlx5dr_domain *dmn,
|
||||||
struct mlx5dr_icm_chunk *chunk,
|
struct mlx5dr_icm_chunk *chunk,
|
||||||
u16 num_of_actions,
|
u16 num_of_actions,
|
||||||
u8 *data);
|
u8 *data);
|
||||||
|
int mlx5dr_send_postsend_args(struct mlx5dr_domain *dmn, u64 arg_id,
|
||||||
|
u16 num_of_actions, u8 *actions_data);
|
||||||
|
|
||||||
int mlx5dr_send_info_pool_create(struct mlx5dr_domain *dmn);
|
int mlx5dr_send_info_pool_create(struct mlx5dr_domain *dmn);
|
||||||
void mlx5dr_send_info_pool_destroy(struct mlx5dr_domain *dmn);
|
void mlx5dr_send_info_pool_destroy(struct mlx5dr_domain *dmn);
|
||||||
|
|
Loading…
Reference in New Issue