#include <infiniband/kern-abi.h>
-#define MLX4_UVERBS_ABI_VERSION 1
+#define MLX4_UVERBS_MIN_ABI_VERSION 2
+#define MLX4_UVERBS_MAX_ABI_VERSION 2
struct mlx4_alloc_ucontext_resp {
struct ibv_get_context_resp ibv_resp;
struct ibv_create_qp ibv_cmd;
__u64 buf_addr;
__u64 db_addr;
+ __u8 log_sq_bb_count;
+ __u8 log_sq_stride;
+ __u8 reserved[6];
};
#endif /* MLX4_ABI_H */
return NULL;
found:
- if (abi_version > MLX4_UVERBS_ABI_VERSION) {
- fprintf(stderr, PFX "Fatal: ABI version %d of %s is too new (expected %d)\n",
- abi_version, uverbs_sys_path, MLX4_UVERBS_ABI_VERSION);
+ if (abi_version < MLX4_UVERBS_MIN_ABI_VERSION ||
+ abi_version > MLX4_UVERBS_MAX_ABI_VERSION) {
+ fprintf(stderr, PFX "Fatal: ABI version %d of %s is not supported "
+ "(min supported %d, max supported %d)\n",
+ abi_version, uverbs_sys_path,
+ MLX4_UVERBS_MIN_ABI_VERSION,
+ MLX4_UVERBS_MAX_ABI_VERSION);
return NULL;
}
struct ibv_recv_wr **bad_wr);
int mlx4_alloc_qp_buf(struct ibv_pd *pd, struct ibv_qp_cap *cap,
enum ibv_qp_type type, struct mlx4_qp *qp);
+void mlx4_set_sq_sizes(struct mlx4_qp *qp, struct ibv_qp_cap *cap,
+ enum ibv_qp_type type);
struct mlx4_qp *mlx4_find_qp(struct mlx4_context *ctx, uint32_t qpn);
int mlx4_store_qp(struct mlx4_context *ctx, uint32_t qpn, struct mlx4_qp *qp);
void mlx4_clear_qp(struct mlx4_context *ctx, uint32_t qpn);
return 0;
}
+void mlx4_set_sq_sizes(struct mlx4_qp *qp, struct ibv_qp_cap *cap,
+ enum ibv_qp_type type)
+{
+ int wqe_size;
+
+ wqe_size = 1 << qp->sq.wqe_shift;
+ switch (type) {
+ case IBV_QPT_UD:
+ wqe_size -= sizeof (struct mlx4_wqe_datagram_seg);
+ break;
+
+ case IBV_QPT_UC:
+ case IBV_QPT_RC:
+ wqe_size -= sizeof (struct mlx4_wqe_raddr_seg);
+ break;
+
+ default:
+ break;
+ }
+
+ qp->sq.max_gs = wqe_size / sizeof (struct mlx4_wqe_data_seg);
+ cap->max_send_sge = qp->sq.max_gs;
+ qp->max_inline_data = wqe_size - sizeof (struct mlx4_wqe_inline_seg);
+ cap->max_inline_data = qp->max_inline_data;
+}
+
struct mlx4_qp *mlx4_find_qp(struct mlx4_context *ctx, uint32_t qpn)
{
int tind = (qpn & (ctx->num_qps - 1)) >> ctx->qp_table_shift;
*qp->db = 0;
- cmd.buf_addr = (uintptr_t) qp->buf.buf;
- cmd.db_addr = (uintptr_t) qp->db;
+ cmd.buf_addr = (uintptr_t) qp->buf.buf;
+ cmd.db_addr = (uintptr_t) qp->db;
+ cmd.log_sq_stride = qp->sq.wqe_shift;
+ for (cmd.log_sq_bb_count = 0;
+ qp->sq.max > 1 << cmd.log_sq_bb_count;
+ ++cmd.log_sq_bb_count)
+ ; /* nothing */
+ memset(cmd.reserved, 0, sizeof cmd.reserved);
ret = ibv_cmd_create_qp(pd, &qp->ibv_qp, attr, &cmd.ibv_cmd, sizeof cmd,
&resp, sizeof resp);
if (ret)
goto err_destroy;
- qp->sq.max = attr->cap.max_send_wr;
- qp->rq.max = attr->cap.max_recv_wr;
- qp->sq.max_gs = attr->cap.max_send_sge;
- qp->rq.max_gs = attr->cap.max_recv_sge;
- qp->max_inline_data = attr->cap.max_inline_data;
+ qp->rq.max = attr->cap.max_recv_wr;
+ qp->rq.max_gs = attr->cap.max_recv_sge;
+ mlx4_set_sq_sizes(qp, &attr->cap, attr->qp_type);
qp->doorbell_qpn = htonl(qp->ibv_qp.qp_num << 8);
if (attr->sq_sig_all)