mirror of
https://github.com/torvalds/linux.git
synced 2024-11-19 10:31:48 +00:00
IB/mlx4: Add support for WQ indirection table related verbs
To enable RSS functionality the IB indirection table object (i.e. ib_rwq_ind_table) should be used. This patch implements the related verbs as of create and destroy an indirection table. In downstream patches the indirection table will be used as part of RSS QP creation. Signed-off-by: Guy Levi <guyle@mellanox.com> Reviewed-by: Yishai Hadas <yishaih@mellanox.com> Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
parent
400b1ebcfe
commit
b8d46ca035
@ -2738,10 +2738,16 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
|
|||||||
ibdev->ib_dev.create_wq = mlx4_ib_create_wq;
|
ibdev->ib_dev.create_wq = mlx4_ib_create_wq;
|
||||||
ibdev->ib_dev.modify_wq = mlx4_ib_modify_wq;
|
ibdev->ib_dev.modify_wq = mlx4_ib_modify_wq;
|
||||||
ibdev->ib_dev.destroy_wq = mlx4_ib_destroy_wq;
|
ibdev->ib_dev.destroy_wq = mlx4_ib_destroy_wq;
|
||||||
|
ibdev->ib_dev.create_rwq_ind_table =
|
||||||
|
mlx4_ib_create_rwq_ind_table;
|
||||||
|
ibdev->ib_dev.destroy_rwq_ind_table =
|
||||||
|
mlx4_ib_destroy_rwq_ind_table;
|
||||||
ibdev->ib_dev.uverbs_ex_cmd_mask |=
|
ibdev->ib_dev.uverbs_ex_cmd_mask |=
|
||||||
(1ull << IB_USER_VERBS_EX_CMD_CREATE_WQ) |
|
(1ull << IB_USER_VERBS_EX_CMD_CREATE_WQ) |
|
||||||
(1ull << IB_USER_VERBS_EX_CMD_MODIFY_WQ) |
|
(1ull << IB_USER_VERBS_EX_CMD_MODIFY_WQ) |
|
||||||
(1ull << IB_USER_VERBS_EX_CMD_DESTROY_WQ);
|
(1ull << IB_USER_VERBS_EX_CMD_DESTROY_WQ) |
|
||||||
|
(1ull << IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL) |
|
||||||
|
(1ull << IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mlx4_is_slave(ibdev->dev)) {
|
if (!mlx4_is_slave(ibdev->dev)) {
|
||||||
|
@ -916,4 +916,10 @@ int mlx4_ib_destroy_wq(struct ib_wq *wq);
|
|||||||
int mlx4_ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,
|
int mlx4_ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,
|
||||||
u32 wq_attr_mask, struct ib_udata *udata);
|
u32 wq_attr_mask, struct ib_udata *udata);
|
||||||
|
|
||||||
|
struct ib_rwq_ind_table
|
||||||
|
*mlx4_ib_create_rwq_ind_table(struct ib_device *device,
|
||||||
|
struct ib_rwq_ind_table_init_attr *init_attr,
|
||||||
|
struct ib_udata *udata);
|
||||||
|
int mlx4_ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *wq_ind_table);
|
||||||
|
|
||||||
#endif /* MLX4_IB_H */
|
#endif /* MLX4_IB_H */
|
||||||
|
@ -3943,3 +3943,73 @@ int mlx4_ib_destroy_wq(struct ib_wq *ibwq)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ib_rwq_ind_table
|
||||||
|
*mlx4_ib_create_rwq_ind_table(struct ib_device *device,
|
||||||
|
struct ib_rwq_ind_table_init_attr *init_attr,
|
||||||
|
struct ib_udata *udata)
|
||||||
|
{
|
||||||
|
struct ib_rwq_ind_table *rwq_ind_table;
|
||||||
|
struct mlx4_ib_create_rwq_ind_tbl_resp resp = {};
|
||||||
|
unsigned int ind_tbl_size = 1 << init_attr->log_ind_tbl_size;
|
||||||
|
unsigned int base_wqn;
|
||||||
|
size_t min_resp_len;
|
||||||
|
int i;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (udata->inlen > 0 &&
|
||||||
|
!ib_is_udata_cleared(udata, 0,
|
||||||
|
udata->inlen))
|
||||||
|
return ERR_PTR(-EOPNOTSUPP);
|
||||||
|
|
||||||
|
min_resp_len = offsetof(typeof(resp), reserved) + sizeof(resp.reserved);
|
||||||
|
if (udata->outlen && udata->outlen < min_resp_len)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
if (ind_tbl_size >
|
||||||
|
device->attrs.rss_caps.max_rwq_indirection_table_size) {
|
||||||
|
pr_debug("log_ind_tbl_size = %d is bigger than supported = %d\n",
|
||||||
|
ind_tbl_size,
|
||||||
|
device->attrs.rss_caps.max_rwq_indirection_table_size);
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
base_wqn = init_attr->ind_tbl[0]->wq_num;
|
||||||
|
|
||||||
|
if (base_wqn % ind_tbl_size) {
|
||||||
|
pr_debug("WQN=0x%x isn't aligned with indirection table size\n",
|
||||||
|
base_wqn);
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 1; i < ind_tbl_size; i++) {
|
||||||
|
if (++base_wqn != init_attr->ind_tbl[i]->wq_num) {
|
||||||
|
pr_debug("indirection table's WQNs aren't consecutive\n");
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rwq_ind_table = kzalloc(sizeof(*rwq_ind_table), GFP_KERNEL);
|
||||||
|
if (!rwq_ind_table)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
if (udata->outlen) {
|
||||||
|
resp.response_length = offsetof(typeof(resp), response_length) +
|
||||||
|
sizeof(resp.response_length);
|
||||||
|
err = ib_copy_to_udata(udata, &resp, resp.response_length);
|
||||||
|
if (err)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rwq_ind_table;
|
||||||
|
|
||||||
|
err:
|
||||||
|
kfree(rwq_ind_table);
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mlx4_ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *ib_rwq_ind_tbl)
|
||||||
|
{
|
||||||
|
kfree(ib_rwq_ind_tbl);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -119,4 +119,8 @@ struct mlx4_ib_modify_wq {
|
|||||||
__u32 reserved;
|
__u32 reserved;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mlx4_ib_create_rwq_ind_tbl_resp {
|
||||||
|
__u32 response_length;
|
||||||
|
__u32 reserved;
|
||||||
|
};
|
||||||
#endif /* MLX4_ABI_USER_H */
|
#endif /* MLX4_ABI_USER_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user