Commit 400b1ebc authored by Guy Levi's avatar Guy Levi Committed by Doug Ledford

IB/mlx4: Add support for WQ related verbs

Support create/modify/destroy WQ related verbs.

The base IB object to enable RSS functionality is a WQ (i.e. ib_wq).
This patch implements the related WQ verbs as of create, modify and
destroy.

In downstream patches the WQ will be used as part of an indirection
table (i.e. ib_rwq_ind_table) to enable RSS QP creation.

Notes:
ConnectX-3 hardware requires consecutive WQNs list as receive descriptor
queues for the RSS QP. Hence, the driver manages consecutive ranges lists
per context which the user must respect.
Destroying the WQ does not return its WQN back to its range for
reusing. However, destroying all WQs from the same range releases the
range and in turn releases its WQNs for reusing.

Since the WQ object is not a natural object in the hardware, the driver
implements the WQ by the hardware QP.

As such, the WQ inherits its port from its RSS QP parent upon its
RST->INIT transition and by that time its state is applied to the
hardware.
Signed-off-by: default avatarGuy Levi <guyle@mellanox.com>
Reviewed-by: default avatarYishai Hadas <yishaih@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent f3301870
...@@ -81,6 +81,8 @@ static const char mlx4_ib_version[] = ...@@ -81,6 +81,8 @@ static const char mlx4_ib_version[] =
DRV_VERSION "\n"; DRV_VERSION "\n";
static void do_slave_init(struct mlx4_ib_dev *ibdev, int slave, int do_init); static void do_slave_init(struct mlx4_ib_dev *ibdev, int slave, int do_init);
static enum rdma_link_layer mlx4_ib_port_link_layer(struct ib_device *device,
u8 port_num);
static struct workqueue_struct *wq; static struct workqueue_struct *wq;
...@@ -552,6 +554,11 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, ...@@ -552,6 +554,11 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
props->timestamp_mask = 0xFFFFFFFFFFFFULL; props->timestamp_mask = 0xFFFFFFFFFFFFULL;
props->max_ah = INT_MAX; props->max_ah = INT_MAX;
if ((dev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS) &&
(mlx4_ib_port_link_layer(ibdev, 1) == IB_LINK_LAYER_ETHERNET ||
mlx4_ib_port_link_layer(ibdev, 2) == IB_LINK_LAYER_ETHERNET))
props->max_wq_type_rq = props->max_qp;
if (!mlx4_is_slave(dev->dev)) if (!mlx4_is_slave(dev->dev))
err = mlx4_get_internal_clock_params(dev->dev, &clock_params); err = mlx4_get_internal_clock_params(dev->dev, &clock_params);
...@@ -1076,6 +1083,9 @@ static struct ib_ucontext *mlx4_ib_alloc_ucontext(struct ib_device *ibdev, ...@@ -1076,6 +1083,9 @@ static struct ib_ucontext *mlx4_ib_alloc_ucontext(struct ib_device *ibdev,
INIT_LIST_HEAD(&context->db_page_list); INIT_LIST_HEAD(&context->db_page_list);
mutex_init(&context->db_page_mutex); mutex_init(&context->db_page_mutex);
INIT_LIST_HEAD(&context->wqn_ranges_list);
mutex_init(&context->wqn_ranges_mutex);
if (ibdev->uverbs_abi_ver == MLX4_IB_UVERBS_NO_DEV_CAPS_ABI_VERSION) if (ibdev->uverbs_abi_ver == MLX4_IB_UVERBS_NO_DEV_CAPS_ABI_VERSION)
err = ib_copy_to_udata(udata, &resp_v3, sizeof(resp_v3)); err = ib_copy_to_udata(udata, &resp_v3, sizeof(resp_v3));
else else
...@@ -2720,6 +2730,20 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) ...@@ -2720,6 +2730,20 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.get_dev_fw_str = get_fw_ver_str; ibdev->ib_dev.get_dev_fw_str = get_fw_ver_str;
ibdev->ib_dev.disassociate_ucontext = mlx4_ib_disassociate_ucontext; ibdev->ib_dev.disassociate_ucontext = mlx4_ib_disassociate_ucontext;
if ((dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS) &&
((mlx4_ib_port_link_layer(&ibdev->ib_dev, 1) ==
IB_LINK_LAYER_ETHERNET) ||
(mlx4_ib_port_link_layer(&ibdev->ib_dev, 2) ==
IB_LINK_LAYER_ETHERNET))) {
ibdev->ib_dev.create_wq = mlx4_ib_create_wq;
ibdev->ib_dev.modify_wq = mlx4_ib_modify_wq;
ibdev->ib_dev.destroy_wq = mlx4_ib_destroy_wq;
ibdev->ib_dev.uverbs_ex_cmd_mask |=
(1ull << IB_USER_VERBS_EX_CMD_CREATE_WQ) |
(1ull << IB_USER_VERBS_EX_CMD_MODIFY_WQ) |
(1ull << IB_USER_VERBS_EX_CMD_DESTROY_WQ);
}
if (!mlx4_is_slave(ibdev->dev)) { if (!mlx4_is_slave(ibdev->dev)) {
ibdev->ib_dev.alloc_fmr = mlx4_ib_fmr_alloc; ibdev->ib_dev.alloc_fmr = mlx4_ib_fmr_alloc;
ibdev->ib_dev.map_phys_fmr = mlx4_ib_map_phys_fmr; ibdev->ib_dev.map_phys_fmr = mlx4_ib_map_phys_fmr;
......
...@@ -88,6 +88,8 @@ struct mlx4_ib_ucontext { ...@@ -88,6 +88,8 @@ struct mlx4_ib_ucontext {
struct list_head db_page_list; struct list_head db_page_list;
struct mutex db_page_mutex; struct mutex db_page_mutex;
struct mlx4_ib_vma_private_data hw_bar_info[HW_BAR_COUNT]; struct mlx4_ib_vma_private_data hw_bar_info[HW_BAR_COUNT];
struct list_head wqn_ranges_list;
struct mutex wqn_ranges_mutex; /* protect wqn_ranges_list */
}; };
struct mlx4_ib_pd { struct mlx4_ib_pd {
...@@ -289,8 +291,19 @@ struct mlx4_roce_smac_vlan_info { ...@@ -289,8 +291,19 @@ struct mlx4_roce_smac_vlan_info {
int update_vid; int update_vid;
}; };
struct mlx4_wqn_range {
int base_wqn;
int size;
int refcount;
bool dirty;
struct list_head list;
};
struct mlx4_ib_qp { struct mlx4_ib_qp {
struct ib_qp ibqp; union {
struct ib_qp ibqp;
struct ib_wq ibwq;
};
struct mlx4_qp mqp; struct mlx4_qp mqp;
struct mlx4_buf buf; struct mlx4_buf buf;
...@@ -329,6 +342,9 @@ struct mlx4_ib_qp { ...@@ -329,6 +342,9 @@ struct mlx4_ib_qp {
struct list_head cq_recv_list; struct list_head cq_recv_list;
struct list_head cq_send_list; struct list_head cq_send_list;
struct counter_index *counter_index; struct counter_index *counter_index;
struct mlx4_wqn_range *wqn_range;
/* Number of RSS QP parents that uses this WQ */
u32 rss_usecnt;
}; };
struct mlx4_ib_srq { struct mlx4_ib_srq {
...@@ -893,4 +909,11 @@ void mlx4_sched_ib_sl2vl_update_work(struct mlx4_ib_dev *ibdev, ...@@ -893,4 +909,11 @@ void mlx4_sched_ib_sl2vl_update_work(struct mlx4_ib_dev *ibdev,
void mlx4_ib_sl2vl_update(struct mlx4_ib_dev *mdev, int port); void mlx4_ib_sl2vl_update(struct mlx4_ib_dev *mdev, int port);
struct ib_wq *mlx4_ib_create_wq(struct ib_pd *pd,
struct ib_wq_init_attr *init_attr,
struct ib_udata *udata);
int mlx4_ib_destroy_wq(struct ib_wq *wq);
int mlx4_ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,
u32 wq_attr_mask, struct ib_udata *udata);
#endif /* MLX4_IB_H */ #endif /* MLX4_IB_H */
This diff is collapsed.
...@@ -105,4 +105,18 @@ struct mlx4_ib_create_qp { ...@@ -105,4 +105,18 @@ struct mlx4_ib_create_qp {
__u8 reserved; __u8 reserved;
}; };
struct mlx4_ib_create_wq {
__u64 buf_addr;
__u64 db_addr;
__u8 log_range_size;
__u8 reserved[3];
__u32 comp_mask;
__u32 reserved1;
};
struct mlx4_ib_modify_wq {
__u32 comp_mask;
__u32 reserved;
};
#endif /* MLX4_ABI_USER_H */ #endif /* MLX4_ABI_USER_H */
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