aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2014-05-29 09:31:03 -0400
committerRoland Dreier <roland@purestorage.com>2014-05-30 00:13:09 -0400
commit99ec41d0a48cb6d14af25765f9449762f9d101f6 (patch)
treeb15baa4835c552a424b9d3ee0e271c4bc5bec273 /drivers/infiniband
parent97982f5a91e91dab26dd0246083b9adf3ba8b2e3 (diff)
mlx4: Add infrastructure for selecting VFs to enable QP0 via MLX proxy QPs
This commit adds the infrastructure for enabling selected VFs to operate SMI (QP0) MADs without restriction. Additionally, for these enabled VFs, their QP0 proxy and tunnel QPs are MLX QPs. As such, they operate over VL15. Therefore, they are not affected by "credit" problems or changes in the VLArb table (which may shut down VL0). Non-enabled VFs may only create UD proxy QP0 qps (which are forced by the hypervisor to send packets using the q-key it assigns and places in the qp-context). Thus, non-enabled VFs will not pose a security risk. The hypervisor discards any privileged MADs it receives from these non-enabled VFs. By default, all VFs are NOT enabled, and must explicitly be enabled by the administrator. The sysfs interface which operates the VF enablement infrastructure is provided in the next commit. Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c52
1 files changed, 40 insertions, 12 deletions
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 2e8c58806e2f..b25600997cb6 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -608,6 +608,16 @@ static int qp_has_rq(struct ib_qp_init_attr *attr)
608 return !attr->srq; 608 return !attr->srq;
609} 609}
610 610
611static int qp0_enabled_vf(struct mlx4_dev *dev, int qpn)
612{
613 int i;
614 for (i = 0; i < dev->caps.num_ports; i++) {
615 if (qpn == dev->caps.qp0_proxy[i])
616 return !!dev->caps.qp0_qkey[i];
617 }
618 return 0;
619}
620
611static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, 621static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
612 struct ib_qp_init_attr *init_attr, 622 struct ib_qp_init_attr *init_attr,
613 struct ib_udata *udata, int sqpn, struct mlx4_ib_qp **caller_qp) 623 struct ib_udata *udata, int sqpn, struct mlx4_ib_qp **caller_qp)
@@ -625,10 +635,13 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
625 !(init_attr->create_flags & MLX4_IB_SRIOV_SQP))) { 635 !(init_attr->create_flags & MLX4_IB_SRIOV_SQP))) {
626 if (init_attr->qp_type == IB_QPT_GSI) 636 if (init_attr->qp_type == IB_QPT_GSI)
627 qp_type = MLX4_IB_QPT_PROXY_GSI; 637 qp_type = MLX4_IB_QPT_PROXY_GSI;
628 else if (mlx4_is_master(dev->dev)) 638 else {
629 qp_type = MLX4_IB_QPT_PROXY_SMI_OWNER; 639 if (mlx4_is_master(dev->dev) ||
630 else 640 qp0_enabled_vf(dev->dev, sqpn))
631 qp_type = MLX4_IB_QPT_PROXY_SMI; 641 qp_type = MLX4_IB_QPT_PROXY_SMI_OWNER;
642 else
643 qp_type = MLX4_IB_QPT_PROXY_SMI;
644 }
632 } 645 }
633 qpn = sqpn; 646 qpn = sqpn;
634 /* add extra sg entry for tunneling */ 647 /* add extra sg entry for tunneling */
@@ -643,7 +656,9 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
643 return -EINVAL; 656 return -EINVAL;
644 if (tnl_init->proxy_qp_type == IB_QPT_GSI) 657 if (tnl_init->proxy_qp_type == IB_QPT_GSI)
645 qp_type = MLX4_IB_QPT_TUN_GSI; 658 qp_type = MLX4_IB_QPT_TUN_GSI;
646 else if (tnl_init->slave == mlx4_master_func_num(dev->dev)) 659 else if (tnl_init->slave == mlx4_master_func_num(dev->dev) ||
660 mlx4_vf_smi_enabled(dev->dev, tnl_init->slave,
661 tnl_init->port))
647 qp_type = MLX4_IB_QPT_TUN_SMI_OWNER; 662 qp_type = MLX4_IB_QPT_TUN_SMI_OWNER;
648 else 663 else
649 qp_type = MLX4_IB_QPT_TUN_SMI; 664 qp_type = MLX4_IB_QPT_TUN_SMI;
@@ -1930,6 +1945,19 @@ out:
1930 return err; 1945 return err;
1931} 1946}
1932 1947
1948static int vf_get_qp0_qkey(struct mlx4_dev *dev, int qpn, u32 *qkey)
1949{
1950 int i;
1951 for (i = 0; i < dev->caps.num_ports; i++) {
1952 if (qpn == dev->caps.qp0_proxy[i] ||
1953 qpn == dev->caps.qp0_tunnel[i]) {
1954 *qkey = dev->caps.qp0_qkey[i];
1955 return 0;
1956 }
1957 }
1958 return -EINVAL;
1959}
1960
1933static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp, 1961static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp,
1934 struct ib_send_wr *wr, 1962 struct ib_send_wr *wr,
1935 void *wqe, unsigned *mlx_seg_len) 1963 void *wqe, unsigned *mlx_seg_len)
@@ -1987,8 +2015,13 @@ static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp,
1987 cpu_to_be32(mdev->dev->caps.qp0_tunnel[sqp->qp.port - 1]); 2015 cpu_to_be32(mdev->dev->caps.qp0_tunnel[sqp->qp.port - 1]);
1988 2016
1989 sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1)); 2017 sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
1990 if (mlx4_get_parav_qkey(mdev->dev, sqp->qp.mqp.qpn, &qkey)) 2018 if (mlx4_is_master(mdev->dev)) {
1991 return -EINVAL; 2019 if (mlx4_get_parav_qkey(mdev->dev, sqp->qp.mqp.qpn, &qkey))
2020 return -EINVAL;
2021 } else {
2022 if (vf_get_qp0_qkey(mdev->dev, sqp->qp.mqp.qpn, &qkey))
2023 return -EINVAL;
2024 }
1992 sqp->ud_header.deth.qkey = cpu_to_be32(qkey); 2025 sqp->ud_header.deth.qkey = cpu_to_be32(qkey);
1993 sqp->ud_header.deth.source_qpn = cpu_to_be32(sqp->qp.mqp.qpn); 2026 sqp->ud_header.deth.source_qpn = cpu_to_be32(sqp->qp.mqp.qpn);
1994 2027
@@ -2682,11 +2715,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
2682 break; 2715 break;
2683 2716
2684 case MLX4_IB_QPT_PROXY_SMI_OWNER: 2717 case MLX4_IB_QPT_PROXY_SMI_OWNER:
2685 if (unlikely(!mlx4_is_master(to_mdev(ibqp->device)->dev))) {
2686 err = -ENOSYS;
2687 *bad_wr = wr;
2688 goto out;
2689 }
2690 err = build_sriov_qp0_header(to_msqp(qp), wr, ctrl, &seglen); 2718 err = build_sriov_qp0_header(to_msqp(qp), wr, ctrl, &seglen);
2691 if (unlikely(err)) { 2719 if (unlikely(err)) {
2692 *bad_wr = wr; 2720 *bad_wr = wr;