Commit 2833c977 authored by Jason Gunthorpe's avatar Jason Gunthorpe

Merge branch 'mlx5_realtime_ts' into rdma.git for-next

Aharon Landau says:

====================
In case device supports only real-time timestamp, the kernel will fail to
create QP despite rdma-core requested such timestamp type.

It is because device returns free-running timestamp, and the conversion
from free-running to real-time is performed in the user space.

This series fixes it, by returning real-time timestamp.
====================

* mlx5_realtime_ts:
  RDMA/mlx5: Support real-time timestamp directly from the device
  RDMA/mlx5: Refactor get_ts_format functions to simplify code
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parents fdcebbc2 33652951
...@@ -725,7 +725,8 @@ static int create_cq_user(struct mlx5_ib_dev *dev, struct ib_udata *udata, ...@@ -725,7 +725,8 @@ static int create_cq_user(struct mlx5_ib_dev *dev, struct ib_udata *udata,
return -EFAULT; return -EFAULT;
if ((ucmd.flags & ~(MLX5_IB_CREATE_CQ_FLAGS_CQE_128B_PAD | if ((ucmd.flags & ~(MLX5_IB_CREATE_CQ_FLAGS_CQE_128B_PAD |
MLX5_IB_CREATE_CQ_FLAGS_UAR_PAGE_INDEX))) MLX5_IB_CREATE_CQ_FLAGS_UAR_PAGE_INDEX |
MLX5_IB_CREATE_CQ_FLAGS_REAL_TIME_TS)))
return -EINVAL; return -EINVAL;
if ((ucmd.cqe_size != 64 && ucmd.cqe_size != 128) || if ((ucmd.cqe_size != 64 && ucmd.cqe_size != 128) ||
...@@ -826,6 +827,9 @@ static int create_cq_user(struct mlx5_ib_dev *dev, struct ib_udata *udata, ...@@ -826,6 +827,9 @@ static int create_cq_user(struct mlx5_ib_dev *dev, struct ib_udata *udata,
cq->private_flags |= MLX5_IB_CQ_PR_FLAGS_CQE_128_PAD; cq->private_flags |= MLX5_IB_CQ_PR_FLAGS_CQE_128_PAD;
} }
if (ucmd.flags & MLX5_IB_CREATE_CQ_FLAGS_REAL_TIME_TS)
cq->private_flags |= MLX5_IB_CQ_PR_FLAGS_REAL_TIME_TS;
MLX5_SET(create_cq_in, *cqb, uid, context->devx_uid); MLX5_SET(create_cq_in, *cqb, uid, context->devx_uid);
return 0; return 0;
......
...@@ -1816,6 +1816,12 @@ static int set_ucontext_resp(struct ib_ucontext *uctx, ...@@ -1816,6 +1816,12 @@ static int set_ucontext_resp(struct ib_ucontext *uctx,
if (MLX5_CAP_GEN(dev->mdev, ece_support)) if (MLX5_CAP_GEN(dev->mdev, ece_support))
resp->comp_mask |= MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_ECE; resp->comp_mask |= MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_ECE;
if (rt_supported(MLX5_CAP_GEN(dev->mdev, sq_ts_format)) &&
rt_supported(MLX5_CAP_GEN(dev->mdev, rq_ts_format)) &&
rt_supported(MLX5_CAP_ROCE(dev->mdev, qp_ts_format)))
resp->comp_mask |=
MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_REAL_TIME_TS;
resp->num_dyn_bfregs = bfregi->num_dyn_bfregs; resp->num_dyn_bfregs = bfregi->num_dyn_bfregs;
if (MLX5_CAP_GEN(dev->mdev, drain_sigerr)) if (MLX5_CAP_GEN(dev->mdev, drain_sigerr))
......
...@@ -549,6 +549,7 @@ static inline const struct mlx5_umr_wr *umr_wr(const struct ib_send_wr *wr) ...@@ -549,6 +549,7 @@ static inline const struct mlx5_umr_wr *umr_wr(const struct ib_send_wr *wr)
enum mlx5_ib_cq_pr_flags { enum mlx5_ib_cq_pr_flags {
MLX5_IB_CQ_PR_FLAGS_CQE_128_PAD = 1 << 0, MLX5_IB_CQ_PR_FLAGS_CQE_128_PAD = 1 << 0,
MLX5_IB_CQ_PR_FLAGS_REAL_TIME_TS = 1 << 1,
}; };
struct mlx5_ib_cq { struct mlx5_ib_cq {
...@@ -1611,4 +1612,10 @@ static inline bool mlx5_ib_lag_should_assign_affinity(struct mlx5_ib_dev *dev) ...@@ -1611,4 +1612,10 @@ static inline bool mlx5_ib_lag_should_assign_affinity(struct mlx5_ib_dev *dev)
(MLX5_CAP_GEN(dev->mdev, num_lag_ports) > 1 && (MLX5_CAP_GEN(dev->mdev, num_lag_ports) > 1 &&
MLX5_CAP_GEN(dev->mdev, lag_tx_port_affinity)); MLX5_CAP_GEN(dev->mdev, lag_tx_port_affinity));
} }
static inline bool rt_supported(int ts_cap)
{
return ts_cap == MLX5_TIMESTAMP_FORMAT_CAP_REAL_TIME ||
ts_cap == MLX5_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME;
}
#endif /* MLX5_IB_H */ #endif /* MLX5_IB_H */
...@@ -1173,69 +1173,79 @@ static void destroy_flow_rule_vport_sq(struct mlx5_ib_sq *sq) ...@@ -1173,69 +1173,79 @@ static void destroy_flow_rule_vport_sq(struct mlx5_ib_sq *sq)
sq->flow_rule = NULL; sq->flow_rule = NULL;
} }
static int get_rq_ts_format(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *send_cq) static bool fr_supported(int ts_cap)
{ {
bool fr_supported = return ts_cap == MLX5_TIMESTAMP_FORMAT_CAP_FREE_RUNNING ||
MLX5_CAP_GEN(dev->mdev, rq_ts_format) == ts_cap == MLX5_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME;
MLX5_RQ_TIMESTAMP_FORMAT_CAP_FREE_RUNNING || }
MLX5_CAP_GEN(dev->mdev, rq_ts_format) ==
MLX5_RQ_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME;
if (send_cq->create_flags & IB_UVERBS_CQ_FLAGS_TIMESTAMP_COMPLETION) { static int get_ts_format(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq,
if (!fr_supported) { bool fr_sup, bool rt_sup)
mlx5_ib_dbg(dev, "Free running TS format is not supported\n"); {
if (cq->private_flags & MLX5_IB_CQ_PR_FLAGS_REAL_TIME_TS) {
if (!rt_sup) {
mlx5_ib_dbg(dev,
"Real time TS format is not supported\n");
return -EOPNOTSUPP;
}
return MLX5_TIMESTAMP_FORMAT_REAL_TIME;
}
if (cq->create_flags & IB_UVERBS_CQ_FLAGS_TIMESTAMP_COMPLETION) {
if (!fr_sup) {
mlx5_ib_dbg(dev,
"Free running TS format is not supported\n");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
return MLX5_RQC_TIMESTAMP_FORMAT_FREE_RUNNING; return MLX5_TIMESTAMP_FORMAT_FREE_RUNNING;
} }
return fr_supported ? MLX5_RQC_TIMESTAMP_FORMAT_FREE_RUNNING : return fr_sup ? MLX5_TIMESTAMP_FORMAT_FREE_RUNNING :
MLX5_RQC_TIMESTAMP_FORMAT_DEFAULT; MLX5_TIMESTAMP_FORMAT_DEFAULT;
}
static int get_rq_ts_format(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *recv_cq)
{
u8 ts_cap = MLX5_CAP_GEN(dev->mdev, rq_ts_format);
return get_ts_format(dev, recv_cq, fr_supported(ts_cap),
rt_supported(ts_cap));
} }
static int get_sq_ts_format(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *send_cq) static int get_sq_ts_format(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *send_cq)
{ {
bool fr_supported = u8 ts_cap = MLX5_CAP_GEN(dev->mdev, sq_ts_format);
MLX5_CAP_GEN(dev->mdev, sq_ts_format) ==
MLX5_SQ_TIMESTAMP_FORMAT_CAP_FREE_RUNNING ||
MLX5_CAP_GEN(dev->mdev, sq_ts_format) ==
MLX5_SQ_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME;
if (send_cq->create_flags & IB_UVERBS_CQ_FLAGS_TIMESTAMP_COMPLETION) { return get_ts_format(dev, send_cq, fr_supported(ts_cap),
if (!fr_supported) { rt_supported(ts_cap));
mlx5_ib_dbg(dev, "Free running TS format is not supported\n");
return -EOPNOTSUPP;
}
return MLX5_SQC_TIMESTAMP_FORMAT_FREE_RUNNING;
}
return fr_supported ? MLX5_SQC_TIMESTAMP_FORMAT_FREE_RUNNING :
MLX5_SQC_TIMESTAMP_FORMAT_DEFAULT;
} }
static int get_qp_ts_format(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *send_cq, static int get_qp_ts_format(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *send_cq,
struct mlx5_ib_cq *recv_cq) struct mlx5_ib_cq *recv_cq)
{ {
bool fr_supported = u8 ts_cap = MLX5_CAP_ROCE(dev->mdev, qp_ts_format);
MLX5_CAP_ROCE(dev->mdev, qp_ts_format) == bool fr_sup = fr_supported(ts_cap);
MLX5_QP_TIMESTAMP_FORMAT_CAP_FREE_RUNNING || bool rt_sup = rt_supported(ts_cap);
MLX5_CAP_ROCE(dev->mdev, qp_ts_format) == u8 default_ts = fr_sup ? MLX5_TIMESTAMP_FORMAT_FREE_RUNNING :
MLX5_QP_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME; MLX5_TIMESTAMP_FORMAT_DEFAULT;
int ts_format = fr_supported ? MLX5_QPC_TIMESTAMP_FORMAT_FREE_RUNNING : int send_ts_format =
MLX5_QPC_TIMESTAMP_FORMAT_DEFAULT; send_cq ? get_ts_format(dev, send_cq, fr_sup, rt_sup) :
default_ts;
if (recv_cq && int recv_ts_format =
recv_cq->create_flags & IB_UVERBS_CQ_FLAGS_TIMESTAMP_COMPLETION) recv_cq ? get_ts_format(dev, recv_cq, fr_sup, rt_sup) :
ts_format = MLX5_QPC_TIMESTAMP_FORMAT_FREE_RUNNING; default_ts;
if (send_cq && if (send_ts_format < 0 || recv_ts_format < 0)
send_cq->create_flags & IB_UVERBS_CQ_FLAGS_TIMESTAMP_COMPLETION) return -EOPNOTSUPP;
ts_format = MLX5_QPC_TIMESTAMP_FORMAT_FREE_RUNNING;
if (send_ts_format != MLX5_TIMESTAMP_FORMAT_DEFAULT &&
if (ts_format == MLX5_QPC_TIMESTAMP_FORMAT_FREE_RUNNING && recv_ts_format != MLX5_TIMESTAMP_FORMAT_DEFAULT &&
!fr_supported) { send_ts_format != recv_ts_format) {
mlx5_ib_dbg(dev, "Free running TS format is not supported\n"); mlx5_ib_dbg(
dev,
"The send ts_format does not match the receive ts_format\n");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
return ts_format;
return send_ts_format == default_ts ? recv_ts_format : send_ts_format;
} }
static int create_raw_packet_qp_sq(struct mlx5_ib_dev *dev, static int create_raw_packet_qp_sq(struct mlx5_ib_dev *dev,
......
...@@ -644,8 +644,8 @@ int mlx5e_create_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param) ...@@ -644,8 +644,8 @@ int mlx5e_create_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param)
return -ENOMEM; return -ENOMEM;
ts_format = mlx5_is_real_time_rq(mdev) ? ts_format = mlx5_is_real_time_rq(mdev) ?
MLX5_RQC_TIMESTAMP_FORMAT_REAL_TIME : MLX5_TIMESTAMP_FORMAT_REAL_TIME :
MLX5_RQC_TIMESTAMP_FORMAT_FREE_RUNNING; MLX5_TIMESTAMP_FORMAT_FREE_RUNNING;
rqc = MLX5_ADDR_OF(create_rq_in, in, ctx); rqc = MLX5_ADDR_OF(create_rq_in, in, ctx);
wq = MLX5_ADDR_OF(rqc, rqc, wq); wq = MLX5_ADDR_OF(rqc, rqc, wq);
...@@ -1188,8 +1188,8 @@ static int mlx5e_create_sq(struct mlx5_core_dev *mdev, ...@@ -1188,8 +1188,8 @@ static int mlx5e_create_sq(struct mlx5_core_dev *mdev,
return -ENOMEM; return -ENOMEM;
ts_format = mlx5_is_real_time_sq(mdev) ? ts_format = mlx5_is_real_time_sq(mdev) ?
MLX5_SQC_TIMESTAMP_FORMAT_REAL_TIME : MLX5_TIMESTAMP_FORMAT_REAL_TIME :
MLX5_SQC_TIMESTAMP_FORMAT_FREE_RUNNING; MLX5_TIMESTAMP_FORMAT_FREE_RUNNING;
sqc = MLX5_ADDR_OF(create_sq_in, in, ctx); sqc = MLX5_ADDR_OF(create_sq_in, in, ctx);
wq = MLX5_ADDR_OF(sqc, sqc, wq); wq = MLX5_ADDR_OF(sqc, sqc, wq);
......
...@@ -37,16 +37,18 @@ static inline bool mlx5_is_real_time_rq(struct mlx5_core_dev *mdev) ...@@ -37,16 +37,18 @@ static inline bool mlx5_is_real_time_rq(struct mlx5_core_dev *mdev)
{ {
u8 rq_ts_format_cap = MLX5_CAP_GEN(mdev, rq_ts_format); u8 rq_ts_format_cap = MLX5_CAP_GEN(mdev, rq_ts_format);
return (rq_ts_format_cap == MLX5_RQ_TIMESTAMP_FORMAT_CAP_REAL_TIME || return (rq_ts_format_cap == MLX5_TIMESTAMP_FORMAT_CAP_REAL_TIME ||
rq_ts_format_cap == MLX5_RQ_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME); rq_ts_format_cap ==
MLX5_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME);
} }
static inline bool mlx5_is_real_time_sq(struct mlx5_core_dev *mdev) static inline bool mlx5_is_real_time_sq(struct mlx5_core_dev *mdev)
{ {
u8 sq_ts_format_cap = MLX5_CAP_GEN(mdev, sq_ts_format); u8 sq_ts_format_cap = MLX5_CAP_GEN(mdev, sq_ts_format);
return (sq_ts_format_cap == MLX5_SQ_TIMESTAMP_FORMAT_CAP_REAL_TIME || return (sq_ts_format_cap == MLX5_TIMESTAMP_FORMAT_CAP_REAL_TIME ||
sq_ts_format_cap == MLX5_SQ_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME); sq_ts_format_cap ==
MLX5_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME);
} }
typedef ktime_t (*cqe_ts_to_ns)(struct mlx5_clock *, u64); typedef ktime_t (*cqe_ts_to_ns)(struct mlx5_clock *, u64);
......
...@@ -953,9 +953,9 @@ struct mlx5_ifc_per_protocol_networking_offload_caps_bits { ...@@ -953,9 +953,9 @@ struct mlx5_ifc_per_protocol_networking_offload_caps_bits {
}; };
enum { enum {
MLX5_QP_TIMESTAMP_FORMAT_CAP_FREE_RUNNING = 0x0, MLX5_TIMESTAMP_FORMAT_CAP_FREE_RUNNING = 0x0,
MLX5_QP_TIMESTAMP_FORMAT_CAP_REAL_TIME = 0x1, MLX5_TIMESTAMP_FORMAT_CAP_REAL_TIME = 0x1,
MLX5_QP_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME = 0x2, MLX5_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME = 0x2,
}; };
struct mlx5_ifc_roce_cap_bits { struct mlx5_ifc_roce_cap_bits {
...@@ -1296,18 +1296,6 @@ enum { ...@@ -1296,18 +1296,6 @@ enum {
MLX5_STEERING_FORMAT_CONNECTX_6DX = 1, MLX5_STEERING_FORMAT_CONNECTX_6DX = 1,
}; };
enum {
MLX5_SQ_TIMESTAMP_FORMAT_CAP_FREE_RUNNING = 0x0,
MLX5_SQ_TIMESTAMP_FORMAT_CAP_REAL_TIME = 0x1,
MLX5_SQ_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME = 0x2,
};
enum {
MLX5_RQ_TIMESTAMP_FORMAT_CAP_FREE_RUNNING = 0x0,
MLX5_RQ_TIMESTAMP_FORMAT_CAP_REAL_TIME = 0x1,
MLX5_RQ_TIMESTAMP_FORMAT_CAP_FREE_RUNNING_AND_REAL_TIME = 0x2,
};
struct mlx5_ifc_cmd_hca_cap_bits { struct mlx5_ifc_cmd_hca_cap_bits {
u8 reserved_at_0[0x1f]; u8 reserved_at_0[0x1f];
u8 vhca_resource_manager[0x1]; u8 vhca_resource_manager[0x1];
...@@ -2944,9 +2932,9 @@ enum { ...@@ -2944,9 +2932,9 @@ enum {
}; };
enum { enum {
MLX5_QPC_TIMESTAMP_FORMAT_FREE_RUNNING = 0x0, MLX5_TIMESTAMP_FORMAT_FREE_RUNNING = 0x0,
MLX5_QPC_TIMESTAMP_FORMAT_DEFAULT = 0x1, MLX5_TIMESTAMP_FORMAT_DEFAULT = 0x1,
MLX5_QPC_TIMESTAMP_FORMAT_REAL_TIME = 0x2, MLX5_TIMESTAMP_FORMAT_REAL_TIME = 0x2,
}; };
struct mlx5_ifc_qpc_bits { struct mlx5_ifc_qpc_bits {
...@@ -3396,12 +3384,6 @@ enum { ...@@ -3396,12 +3384,6 @@ enum {
MLX5_SQC_STATE_ERR = 0x3, MLX5_SQC_STATE_ERR = 0x3,
}; };
enum {
MLX5_SQC_TIMESTAMP_FORMAT_FREE_RUNNING = 0x0,
MLX5_SQC_TIMESTAMP_FORMAT_DEFAULT = 0x1,
MLX5_SQC_TIMESTAMP_FORMAT_REAL_TIME = 0x2,
};
struct mlx5_ifc_sqc_bits { struct mlx5_ifc_sqc_bits {
u8 rlky[0x1]; u8 rlky[0x1];
u8 cd_master[0x1]; u8 cd_master[0x1];
...@@ -3507,12 +3489,6 @@ enum { ...@@ -3507,12 +3489,6 @@ enum {
MLX5_RQC_STATE_ERR = 0x3, MLX5_RQC_STATE_ERR = 0x3,
}; };
enum {
MLX5_RQC_TIMESTAMP_FORMAT_FREE_RUNNING = 0x0,
MLX5_RQC_TIMESTAMP_FORMAT_DEFAULT = 0x1,
MLX5_RQC_TIMESTAMP_FORMAT_REAL_TIME = 0x2,
};
struct mlx5_ifc_rqc_bits { struct mlx5_ifc_rqc_bits {
u8 rlky[0x1]; u8 rlky[0x1];
u8 delay_drop_en[0x1]; u8 delay_drop_en[0x1];
......
...@@ -550,8 +550,8 @@ static inline const char *mlx5_qp_state_str(int state) ...@@ -550,8 +550,8 @@ static inline const char *mlx5_qp_state_str(int state)
static inline int mlx5_get_qp_default_ts(struct mlx5_core_dev *dev) static inline int mlx5_get_qp_default_ts(struct mlx5_core_dev *dev)
{ {
return !MLX5_CAP_ROCE(dev, qp_ts_format) ? return !MLX5_CAP_ROCE(dev, qp_ts_format) ?
MLX5_QPC_TIMESTAMP_FORMAT_FREE_RUNNING : MLX5_TIMESTAMP_FORMAT_FREE_RUNNING :
MLX5_QPC_TIMESTAMP_FORMAT_DEFAULT; MLX5_TIMESTAMP_FORMAT_DEFAULT;
} }
#endif /* MLX5_QP_H */ #endif /* MLX5_QP_H */
...@@ -102,6 +102,7 @@ enum mlx5_ib_alloc_ucontext_resp_mask { ...@@ -102,6 +102,7 @@ enum mlx5_ib_alloc_ucontext_resp_mask {
MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_DUMP_FILL_MKEY = 1UL << 1, MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_DUMP_FILL_MKEY = 1UL << 1,
MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_ECE = 1UL << 2, MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_ECE = 1UL << 2,
MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_SQD2RTS = 1UL << 3, MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_SQD2RTS = 1UL << 3,
MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_REAL_TIME_TS = 1UL << 4,
}; };
enum mlx5_user_cmds_supp_uhw { enum mlx5_user_cmds_supp_uhw {
...@@ -271,6 +272,7 @@ struct mlx5_ib_query_device_resp { ...@@ -271,6 +272,7 @@ struct mlx5_ib_query_device_resp {
enum mlx5_ib_create_cq_flags { enum mlx5_ib_create_cq_flags {
MLX5_IB_CREATE_CQ_FLAGS_CQE_128B_PAD = 1 << 0, MLX5_IB_CREATE_CQ_FLAGS_CQE_128B_PAD = 1 << 0,
MLX5_IB_CREATE_CQ_FLAGS_UAR_PAGE_INDEX = 1 << 1, MLX5_IB_CREATE_CQ_FLAGS_UAR_PAGE_INDEX = 1 << 1,
MLX5_IB_CREATE_CQ_FLAGS_REAL_TIME_TS = 1 << 2,
}; };
struct mlx5_ib_create_cq { struct mlx5_ib_create_cq {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment