IB/mlx4: Add support for steerable IB UD QPs
This patch adds support for steerable (NETIF) QP creation. When we create the device, we allocate a range of steerable QPs. Afterward when a QP is created with the NETIF flag, it's allocated from this range. Allocation is managed by bitmap allocator. Internal steering rules for those QPs is automatically generated on their creation. Signed-off-by: Matan Barak <matanb@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
Родитель
a37a1a4284
Коммит
c1c9850112
|
@ -1850,8 +1850,35 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
|
|||
spin_lock_init(&ibdev->sm_lock);
|
||||
mutex_init(&ibdev->cap_mask_mutex);
|
||||
|
||||
if (ibdev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED) {
|
||||
ibdev->steer_qpn_count = MLX4_IB_UC_MAX_NUM_QPS;
|
||||
err = mlx4_qp_reserve_range(dev, ibdev->steer_qpn_count,
|
||||
MLX4_IB_UC_STEER_QPN_ALIGN,
|
||||
&ibdev->steer_qpn_base);
|
||||
if (err)
|
||||
goto err_counter;
|
||||
|
||||
ibdev->ib_uc_qpns_bitmap =
|
||||
kmalloc(BITS_TO_LONGS(ibdev->steer_qpn_count) *
|
||||
sizeof(long),
|
||||
GFP_KERNEL);
|
||||
if (!ibdev->ib_uc_qpns_bitmap) {
|
||||
dev_err(&dev->pdev->dev, "bit map alloc failed\n");
|
||||
goto err_steer_qp_release;
|
||||
}
|
||||
|
||||
bitmap_zero(ibdev->ib_uc_qpns_bitmap, ibdev->steer_qpn_count);
|
||||
|
||||
err = mlx4_FLOW_STEERING_IB_UC_QP_RANGE(
|
||||
dev, ibdev->steer_qpn_base,
|
||||
ibdev->steer_qpn_base +
|
||||
ibdev->steer_qpn_count - 1);
|
||||
if (err)
|
||||
goto err_steer_free_bitmap;
|
||||
}
|
||||
|
||||
if (ib_register_device(&ibdev->ib_dev, NULL))
|
||||
goto err_counter;
|
||||
goto err_steer_free_bitmap;
|
||||
|
||||
if (mlx4_ib_mad_init(ibdev))
|
||||
goto err_reg;
|
||||
|
@ -1902,6 +1929,13 @@ err_mad:
|
|||
err_reg:
|
||||
ib_unregister_device(&ibdev->ib_dev);
|
||||
|
||||
err_steer_free_bitmap:
|
||||
kfree(ibdev->ib_uc_qpns_bitmap);
|
||||
|
||||
err_steer_qp_release:
|
||||
if (ibdev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED)
|
||||
mlx4_qp_release_range(dev, ibdev->steer_qpn_base,
|
||||
ibdev->steer_qpn_count);
|
||||
err_counter:
|
||||
for (; i; --i)
|
||||
if (ibdev->counters[i - 1] != -1)
|
||||
|
@ -1922,6 +1956,69 @@ err_dealloc:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int mlx4_ib_steer_qp_alloc(struct mlx4_ib_dev *dev, int count, int *qpn)
|
||||
{
|
||||
int offset;
|
||||
|
||||
WARN_ON(!dev->ib_uc_qpns_bitmap);
|
||||
|
||||
offset = bitmap_find_free_region(dev->ib_uc_qpns_bitmap,
|
||||
dev->steer_qpn_count,
|
||||
get_count_order(count));
|
||||
if (offset < 0)
|
||||
return offset;
|
||||
|
||||
*qpn = dev->steer_qpn_base + offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx4_ib_steer_qp_free(struct mlx4_ib_dev *dev, u32 qpn, int count)
|
||||
{
|
||||
if (!qpn ||
|
||||
dev->steering_support != MLX4_STEERING_MODE_DEVICE_MANAGED)
|
||||
return;
|
||||
|
||||
BUG_ON(qpn < dev->steer_qpn_base);
|
||||
|
||||
bitmap_release_region(dev->ib_uc_qpns_bitmap,
|
||||
qpn - dev->steer_qpn_base,
|
||||
get_count_order(count));
|
||||
}
|
||||
|
||||
int mlx4_ib_steer_qp_reg(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
|
||||
int is_attach)
|
||||
{
|
||||
int err;
|
||||
size_t flow_size;
|
||||
struct ib_flow_attr *flow = NULL;
|
||||
struct ib_flow_spec_ib *ib_spec;
|
||||
|
||||
if (is_attach) {
|
||||
flow_size = sizeof(struct ib_flow_attr) +
|
||||
sizeof(struct ib_flow_spec_ib);
|
||||
flow = kzalloc(flow_size, GFP_KERNEL);
|
||||
if (!flow)
|
||||
return -ENOMEM;
|
||||
flow->port = mqp->port;
|
||||
flow->num_of_specs = 1;
|
||||
flow->size = flow_size;
|
||||
ib_spec = (struct ib_flow_spec_ib *)(flow + 1);
|
||||
ib_spec->type = IB_FLOW_SPEC_IB;
|
||||
ib_spec->size = sizeof(struct ib_flow_spec_ib);
|
||||
/* Add an empty rule for IB L2 */
|
||||
memset(&ib_spec->mask, 0, sizeof(ib_spec->mask));
|
||||
|
||||
err = __mlx4_ib_create_flow(&mqp->ibqp, flow,
|
||||
IB_FLOW_DOMAIN_NIC,
|
||||
MLX4_FS_REGULAR,
|
||||
&mqp->reg_id);
|
||||
} else {
|
||||
err = __mlx4_ib_destroy_flow(mdev->dev, mqp->reg_id);
|
||||
}
|
||||
kfree(flow);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
|
||||
{
|
||||
struct mlx4_ib_dev *ibdev = ibdev_ptr;
|
||||
|
@ -1935,6 +2032,13 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
|
|||
pr_warn("failure unregistering notifier\n");
|
||||
ibdev->iboe.nb.notifier_call = NULL;
|
||||
}
|
||||
|
||||
if (ibdev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED) {
|
||||
mlx4_qp_release_range(dev, ibdev->steer_qpn_base,
|
||||
ibdev->steer_qpn_count);
|
||||
kfree(ibdev->ib_uc_qpns_bitmap);
|
||||
}
|
||||
|
||||
iounmap(ibdev->uar_map);
|
||||
for (p = 0; p < ibdev->num_ports; ++p)
|
||||
if (ibdev->counters[p] != -1)
|
||||
|
|
|
@ -68,6 +68,8 @@ enum {
|
|||
/*module param to indicate if SM assigns the alias_GUID*/
|
||||
extern int mlx4_ib_sm_guid_assign;
|
||||
|
||||
#define MLX4_IB_UC_STEER_QPN_ALIGN 1
|
||||
#define MLX4_IB_UC_MAX_NUM_QPS 256
|
||||
struct mlx4_ib_ucontext {
|
||||
struct ib_ucontext ibucontext;
|
||||
struct mlx4_uar uar;
|
||||
|
@ -153,6 +155,7 @@ struct mlx4_ib_wq {
|
|||
enum mlx4_ib_qp_flags {
|
||||
MLX4_IB_QP_LSO = IB_QP_CREATE_IPOIB_UD_LSO,
|
||||
MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK = IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK,
|
||||
MLX4_IB_QP_NETIF = IB_QP_CREATE_NETIF_QP,
|
||||
MLX4_IB_SRIOV_TUNNEL_QP = 1 << 30,
|
||||
MLX4_IB_SRIOV_SQP = 1 << 31,
|
||||
};
|
||||
|
@ -270,6 +273,7 @@ struct mlx4_ib_qp {
|
|||
struct list_head gid_list;
|
||||
struct list_head steering_rules;
|
||||
struct mlx4_ib_buf *sqp_proxy_rcv;
|
||||
u64 reg_id;
|
||||
|
||||
};
|
||||
|
||||
|
@ -494,6 +498,9 @@ struct mlx4_ib_dev {
|
|||
struct kobject *dev_ports_parent[MLX4_MFUNC_MAX];
|
||||
struct mlx4_ib_iov_port iov_ports[MLX4_MAX_PORTS];
|
||||
struct pkey_mgt pkeys;
|
||||
unsigned long *ib_uc_qpns_bitmap;
|
||||
int steer_qpn_count;
|
||||
int steer_qpn_base;
|
||||
int steering_support;
|
||||
};
|
||||
|
||||
|
@ -753,5 +760,9 @@ void mlx4_ib_device_unregister_sysfs(struct mlx4_ib_dev *device);
|
|||
|
||||
__be64 mlx4_ib_gen_node_guid(void);
|
||||
|
||||
int mlx4_ib_steer_qp_alloc(struct mlx4_ib_dev *dev, int count, int *qpn);
|
||||
void mlx4_ib_steer_qp_free(struct mlx4_ib_dev *dev, u32 qpn, int count);
|
||||
int mlx4_ib_steer_qp_reg(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
|
||||
int is_attach);
|
||||
|
||||
#endif /* MLX4_IB_H */
|
||||
|
|
|
@ -716,6 +716,14 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
|
|||
if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO)
|
||||
qp->flags |= MLX4_IB_QP_LSO;
|
||||
|
||||
if (init_attr->create_flags & IB_QP_CREATE_NETIF_QP) {
|
||||
if (dev->steering_support ==
|
||||
MLX4_STEERING_MODE_DEVICE_MANAGED)
|
||||
qp->flags |= MLX4_IB_QP_NETIF;
|
||||
else
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = set_kernel_sq_size(dev, &init_attr->cap, qp_type, qp);
|
||||
if (err)
|
||||
goto err;
|
||||
|
@ -765,7 +773,11 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
|
|||
if (init_attr->qp_type == IB_QPT_RAW_PACKET)
|
||||
err = mlx4_qp_reserve_range(dev->dev, 1, 1 << 8, &qpn);
|
||||
else
|
||||
err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn);
|
||||
if (qp->flags & MLX4_IB_QP_NETIF)
|
||||
err = mlx4_ib_steer_qp_alloc(dev, 1, &qpn);
|
||||
else
|
||||
err = mlx4_qp_reserve_range(dev->dev, 1, 1,
|
||||
&qpn);
|
||||
if (err)
|
||||
goto err_proxy;
|
||||
}
|
||||
|
@ -790,8 +802,12 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
|
|||
return 0;
|
||||
|
||||
err_qpn:
|
||||
if (!sqpn)
|
||||
mlx4_qp_release_range(dev->dev, qpn, 1);
|
||||
if (!sqpn) {
|
||||
if (qp->flags & MLX4_IB_QP_NETIF)
|
||||
mlx4_ib_steer_qp_free(dev, qpn, 1);
|
||||
else
|
||||
mlx4_qp_release_range(dev->dev, qpn, 1);
|
||||
}
|
||||
err_proxy:
|
||||
if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI)
|
||||
free_proxy_bufs(pd->device, qp);
|
||||
|
@ -932,8 +948,12 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
|
|||
|
||||
mlx4_qp_free(dev->dev, &qp->mqp);
|
||||
|
||||
if (!is_sqp(dev, qp) && !is_tunnel_qp(dev, qp))
|
||||
mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1);
|
||||
if (!is_sqp(dev, qp) && !is_tunnel_qp(dev, qp)) {
|
||||
if (qp->flags & MLX4_IB_QP_NETIF)
|
||||
mlx4_ib_steer_qp_free(dev, qp->mqp.qpn, 1);
|
||||
else
|
||||
mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1);
|
||||
}
|
||||
|
||||
mlx4_mtt_cleanup(dev->dev, &qp->mtt);
|
||||
|
||||
|
@ -987,9 +1007,16 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
|
|||
*/
|
||||
if (init_attr->create_flags & ~(MLX4_IB_QP_LSO |
|
||||
MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK |
|
||||
MLX4_IB_SRIOV_TUNNEL_QP | MLX4_IB_SRIOV_SQP))
|
||||
MLX4_IB_SRIOV_TUNNEL_QP |
|
||||
MLX4_IB_SRIOV_SQP |
|
||||
MLX4_IB_QP_NETIF))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (init_attr->create_flags & IB_QP_CREATE_NETIF_QP) {
|
||||
if (init_attr->qp_type != IB_QPT_UD)
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (init_attr->create_flags &&
|
||||
(udata ||
|
||||
((init_attr->create_flags & ~MLX4_IB_SRIOV_SQP) &&
|
||||
|
@ -1235,6 +1262,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
|||
struct mlx4_qp_context *context;
|
||||
enum mlx4_qp_optpar optpar = 0;
|
||||
int sqd_event;
|
||||
int steer_qp = 0;
|
||||
int err = -EINVAL;
|
||||
|
||||
context = kzalloc(sizeof *context, GFP_KERNEL);
|
||||
|
@ -1319,6 +1347,11 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
|||
optpar |= MLX4_QP_OPTPAR_COUNTER_INDEX;
|
||||
} else
|
||||
context->pri_path.counter_index = 0xff;
|
||||
|
||||
if (qp->flags & MLX4_IB_QP_NETIF) {
|
||||
mlx4_ib_steer_qp_reg(dev, qp, 1);
|
||||
steer_qp = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr_mask & IB_QP_PKEY_INDEX) {
|
||||
|
@ -1547,9 +1580,14 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
|||
qp->sq_next_wqe = 0;
|
||||
if (qp->rq.wqe_cnt)
|
||||
*qp->db.db = 0;
|
||||
|
||||
if (qp->flags & MLX4_IB_QP_NETIF)
|
||||
mlx4_ib_steer_qp_reg(dev, qp, 0);
|
||||
}
|
||||
|
||||
out:
|
||||
if (err && steer_qp)
|
||||
mlx4_ib_steer_qp_reg(dev, qp, 0);
|
||||
kfree(context);
|
||||
return err;
|
||||
}
|
||||
|
@ -2762,6 +2800,9 @@ done:
|
|||
if (qp->flags & MLX4_IB_QP_LSO)
|
||||
qp_init_attr->create_flags |= IB_QP_CREATE_IPOIB_UD_LSO;
|
||||
|
||||
if (qp->flags & MLX4_IB_QP_NETIF)
|
||||
qp_init_attr->create_flags |= IB_QP_CREATE_NETIF_QP;
|
||||
|
||||
qp_init_attr->sq_sig_type =
|
||||
qp->sq_signal_bits == cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE) ?
|
||||
IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
|
||||
|
|
Загрузка…
Ссылка в новой задаче