aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c52
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c13
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c44
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h8
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c26
-rw-r--r--include/linux/mlx4/device.h1
8 files changed, 126 insertions, 35 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;
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index b0e48d426fce..26c3ebaa49d1 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1666,6 +1666,8 @@ static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
1666 for (port = min_port; port <= max_port; port++) { 1666 for (port = min_port; port <= max_port; port++) {
1667 if (!test_bit(port - 1, actv_ports.ports)) 1667 if (!test_bit(port - 1, actv_ports.ports))
1668 continue; 1668 continue;
1669 priv->mfunc.master.vf_oper[slave].smi_enabled[port] =
1670 priv->mfunc.master.vf_admin[slave].enable_smi[port];
1669 vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; 1671 vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
1670 vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port]; 1672 vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
1671 vp_oper->state = *vp_admin; 1673 vp_oper->state = *vp_admin;
@@ -1717,6 +1719,8 @@ static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave
1717 for (port = min_port; port <= max_port; port++) { 1719 for (port = min_port; port <= max_port; port++) {
1718 if (!test_bit(port - 1, actv_ports.ports)) 1720 if (!test_bit(port - 1, actv_ports.ports))
1719 continue; 1721 continue;
1722 priv->mfunc.master.vf_oper[slave].smi_enabled[port] =
1723 MLX4_VF_SMI_DISABLED;
1720 vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; 1724 vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
1721 if (NO_INDX != vp_oper->vlan_idx) { 1725 if (NO_INDX != vp_oper->vlan_idx) {
1722 __mlx4_unregister_vlan(&priv->dev, 1726 __mlx4_unregister_vlan(&priv->dev,
@@ -2553,6 +2557,13 @@ EXPORT_SYMBOL_GPL(mlx4_set_vf_link_state);
2553 2557
2554int mlx4_vf_smi_enabled(struct mlx4_dev *dev, int slave, int port) 2558int mlx4_vf_smi_enabled(struct mlx4_dev *dev, int slave, int port)
2555{ 2559{
2556 return 0; 2560 struct mlx4_priv *priv = mlx4_priv(dev);
2561
2562 if (slave < 1 || slave >= dev->num_slaves ||
2563 port < 1 || port > MLX4_MAX_PORTS)
2564 return 0;
2565
2566 return priv->mfunc.master.vf_oper[slave].smi_enabled[port] ==
2567 MLX4_VF_SMI_ENABLED;
2557} 2568}
2558EXPORT_SYMBOL_GPL(mlx4_vf_smi_enabled); 2569EXPORT_SYMBOL_GPL(mlx4_vf_smi_enabled);
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index ef242e19766f..01e6dd61ee3c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -178,8 +178,8 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
178 struct mlx4_cmd_info *cmd) 178 struct mlx4_cmd_info *cmd)
179{ 179{
180 struct mlx4_priv *priv = mlx4_priv(dev); 180 struct mlx4_priv *priv = mlx4_priv(dev);
181 u8 field; 181 u8 field, port;
182 u32 size; 182 u32 size, proxy_qp, qkey;
183 int err = 0; 183 int err = 0;
184 184
185#define QUERY_FUNC_CAP_FLAGS_OFFSET 0x0 185#define QUERY_FUNC_CAP_FLAGS_OFFSET 0x0
@@ -209,6 +209,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
209 209
210/* when opcode modifier = 1 */ 210/* when opcode modifier = 1 */
211#define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3 211#define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3
212#define QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET 0x4
212#define QUERY_FUNC_CAP_FLAGS0_OFFSET 0x8 213#define QUERY_FUNC_CAP_FLAGS0_OFFSET 0x8
213#define QUERY_FUNC_CAP_FLAGS1_OFFSET 0xc 214#define QUERY_FUNC_CAP_FLAGS1_OFFSET 0xc
214 215
@@ -221,6 +222,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
221#define QUERY_FUNC_CAP_FLAGS1_FORCE_MAC 0x40 222#define QUERY_FUNC_CAP_FLAGS1_FORCE_MAC 0x40
222#define QUERY_FUNC_CAP_FLAGS1_FORCE_VLAN 0x80 223#define QUERY_FUNC_CAP_FLAGS1_FORCE_VLAN 0x80
223#define QUERY_FUNC_CAP_FLAGS1_NIC_INFO 0x10 224#define QUERY_FUNC_CAP_FLAGS1_NIC_INFO 0x10
225#define QUERY_FUNC_CAP_VF_ENABLE_QP0 0x08
224 226
225#define QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID 0x80 227#define QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID 0x80
226 228
@@ -234,28 +236,35 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
234 return -EINVAL; 236 return -EINVAL;
235 237
236 vhcr->in_modifier = converted_port; 238 vhcr->in_modifier = converted_port;
237 /* Set nic_info bit to mark new fields support */
238 field = QUERY_FUNC_CAP_FLAGS1_NIC_INFO;
239 MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS1_OFFSET);
240
241 /* phys-port = logical-port */ 239 /* phys-port = logical-port */
242 field = vhcr->in_modifier - 240 field = vhcr->in_modifier -
243 find_first_bit(actv_ports.ports, dev->caps.num_ports); 241 find_first_bit(actv_ports.ports, dev->caps.num_ports);
244 MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_PHYS_PORT_OFFSET); 242 MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_PHYS_PORT_OFFSET);
245 243
246 field = vhcr->in_modifier; 244 port = vhcr->in_modifier;
245 proxy_qp = dev->phys_caps.base_proxy_sqpn + 8 * slave + port - 1;
246
247 /* Set nic_info bit to mark new fields support */
248 field = QUERY_FUNC_CAP_FLAGS1_NIC_INFO;
249
250 if (mlx4_vf_smi_enabled(dev, slave, port) &&
251 !mlx4_get_parav_qkey(dev, proxy_qp, &qkey)) {
252 field |= QUERY_FUNC_CAP_VF_ENABLE_QP0;
253 MLX4_PUT(outbox->buf, qkey,
254 QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET);
255 }
256 MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS1_OFFSET);
257
247 /* size is now the QP number */ 258 /* size is now the QP number */
248 size = dev->phys_caps.base_tunnel_sqpn + 8 * slave + field - 1; 259 size = dev->phys_caps.base_tunnel_sqpn + 8 * slave + port - 1;
249 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_TUNNEL); 260 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_TUNNEL);
250 261
251 size += 2; 262 size += 2;
252 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_TUNNEL); 263 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_TUNNEL);
253 264
254 size = dev->phys_caps.base_proxy_sqpn + 8 * slave + field - 1; 265 MLX4_PUT(outbox->buf, proxy_qp, QUERY_FUNC_CAP_QP0_PROXY);
255 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_PROXY); 266 proxy_qp += 2;
256 267 MLX4_PUT(outbox->buf, proxy_qp, QUERY_FUNC_CAP_QP1_PROXY);
257 size += 2;
258 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_PROXY);
259 268
260 MLX4_PUT(outbox->buf, dev->caps.phys_port_id[vhcr->in_modifier], 269 MLX4_PUT(outbox->buf, dev->caps.phys_port_id[vhcr->in_modifier],
261 QUERY_FUNC_CAP_PHYS_PORT_ID); 270 QUERY_FUNC_CAP_PHYS_PORT_ID);
@@ -326,7 +335,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
326 struct mlx4_cmd_mailbox *mailbox; 335 struct mlx4_cmd_mailbox *mailbox;
327 u32 *outbox; 336 u32 *outbox;
328 u8 field, op_modifier; 337 u8 field, op_modifier;
329 u32 size; 338 u32 size, qkey;
330 int err = 0, quotas = 0; 339 int err = 0, quotas = 0;
331 340
332 op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */ 341 op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */
@@ -442,6 +451,13 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
442 goto out; 451 goto out;
443 } 452 }
444 453
454 if (func_cap->flags1 & QUERY_FUNC_CAP_VF_ENABLE_QP0) {
455 MLX4_GET(qkey, outbox, QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET);
456 func_cap->qp0_qkey = qkey;
457 } else {
458 func_cap->qp0_qkey = 0;
459 }
460
445 MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_TUNNEL); 461 MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_TUNNEL);
446 func_cap->qp0_tunnel_qpn = size & 0xFFFFFF; 462 func_cap->qp0_tunnel_qpn = size & 0xFFFFFF;
447 463
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h
index 6811ee00ba7c..1fce03ebe5c4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.h
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.h
@@ -134,6 +134,7 @@ struct mlx4_func_cap {
134 int max_eq; 134 int max_eq;
135 int reserved_eq; 135 int reserved_eq;
136 int mcg_quota; 136 int mcg_quota;
137 u32 qp0_qkey;
137 u32 qp0_tunnel_qpn; 138 u32 qp0_tunnel_qpn;
138 u32 qp0_proxy_qpn; 139 u32 qp0_proxy_qpn;
139 u32 qp1_tunnel_qpn; 140 u32 qp1_tunnel_qpn;
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 12a7ee2e6098..908326876ab5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -666,13 +666,15 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
666 return -ENODEV; 666 return -ENODEV;
667 } 667 }
668 668
669 dev->caps.qp0_qkey = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);
669 dev->caps.qp0_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL); 670 dev->caps.qp0_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
670 dev->caps.qp0_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL); 671 dev->caps.qp0_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
671 dev->caps.qp1_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL); 672 dev->caps.qp1_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
672 dev->caps.qp1_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL); 673 dev->caps.qp1_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
673 674
674 if (!dev->caps.qp0_tunnel || !dev->caps.qp0_proxy || 675 if (!dev->caps.qp0_tunnel || !dev->caps.qp0_proxy ||
675 !dev->caps.qp1_tunnel || !dev->caps.qp1_proxy) { 676 !dev->caps.qp1_tunnel || !dev->caps.qp1_proxy ||
677 !dev->caps.qp0_qkey) {
676 err = -ENOMEM; 678 err = -ENOMEM;
677 goto err_mem; 679 goto err_mem;
678 } 680 }
@@ -684,6 +686,7 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
684 " port %d, aborting (%d).\n", i, err); 686 " port %d, aborting (%d).\n", i, err);
685 goto err_mem; 687 goto err_mem;
686 } 688 }
689 dev->caps.qp0_qkey[i - 1] = func_cap.qp0_qkey;
687 dev->caps.qp0_tunnel[i - 1] = func_cap.qp0_tunnel_qpn; 690 dev->caps.qp0_tunnel[i - 1] = func_cap.qp0_tunnel_qpn;
688 dev->caps.qp0_proxy[i - 1] = func_cap.qp0_proxy_qpn; 691 dev->caps.qp0_proxy[i - 1] = func_cap.qp0_proxy_qpn;
689 dev->caps.qp1_tunnel[i - 1] = func_cap.qp1_tunnel_qpn; 692 dev->caps.qp1_tunnel[i - 1] = func_cap.qp1_tunnel_qpn;
@@ -729,12 +732,16 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
729 return 0; 732 return 0;
730 733
731err_mem: 734err_mem:
735 kfree(dev->caps.qp0_qkey);
732 kfree(dev->caps.qp0_tunnel); 736 kfree(dev->caps.qp0_tunnel);
733 kfree(dev->caps.qp0_proxy); 737 kfree(dev->caps.qp0_proxy);
734 kfree(dev->caps.qp1_tunnel); 738 kfree(dev->caps.qp1_tunnel);
735 kfree(dev->caps.qp1_proxy); 739 kfree(dev->caps.qp1_proxy);
736 dev->caps.qp0_tunnel = dev->caps.qp0_proxy = 740 dev->caps.qp0_qkey = NULL;
737 dev->caps.qp1_tunnel = dev->caps.qp1_proxy = NULL; 741 dev->caps.qp0_tunnel = NULL;
742 dev->caps.qp0_proxy = NULL;
743 dev->caps.qp1_tunnel = NULL;
744 dev->caps.qp1_proxy = NULL;
738 745
739 return err; 746 return err;
740} 747}
@@ -1697,6 +1704,7 @@ unmap_bf:
1697 unmap_bf_area(dev); 1704 unmap_bf_area(dev);
1698 1705
1699 if (mlx4_is_slave(dev)) { 1706 if (mlx4_is_slave(dev)) {
1707 kfree(dev->caps.qp0_qkey);
1700 kfree(dev->caps.qp0_tunnel); 1708 kfree(dev->caps.qp0_tunnel);
1701 kfree(dev->caps.qp0_proxy); 1709 kfree(dev->caps.qp0_proxy);
1702 kfree(dev->caps.qp1_tunnel); 1710 kfree(dev->caps.qp1_tunnel);
@@ -2573,6 +2581,7 @@ err_master_mfunc:
2573 mlx4_multi_func_cleanup(dev); 2581 mlx4_multi_func_cleanup(dev);
2574 2582
2575 if (mlx4_is_slave(dev)) { 2583 if (mlx4_is_slave(dev)) {
2584 kfree(dev->caps.qp0_qkey);
2576 kfree(dev->caps.qp0_tunnel); 2585 kfree(dev->caps.qp0_tunnel);
2577 kfree(dev->caps.qp0_proxy); 2586 kfree(dev->caps.qp0_proxy);
2578 kfree(dev->caps.qp1_tunnel); 2587 kfree(dev->caps.qp1_tunnel);
@@ -2702,6 +2711,7 @@ static void __mlx4_remove_one(struct pci_dev *pdev)
2702 if (!mlx4_is_slave(dev)) 2711 if (!mlx4_is_slave(dev))
2703 mlx4_free_ownership(dev); 2712 mlx4_free_ownership(dev);
2704 2713
2714 kfree(dev->caps.qp0_qkey);
2705 kfree(dev->caps.qp0_tunnel); 2715 kfree(dev->caps.qp0_tunnel);
2706 kfree(dev->caps.qp0_proxy); 2716 kfree(dev->caps.qp0_proxy);
2707 kfree(dev->caps.qp1_tunnel); 2717 kfree(dev->caps.qp1_tunnel);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index f9c465101963..0efd1738fcb3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -133,6 +133,11 @@ enum {
133 MLX4_COMM_CMD_FLR = 254 133 MLX4_COMM_CMD_FLR = 254
134}; 134};
135 135
136enum {
137 MLX4_VF_SMI_DISABLED,
138 MLX4_VF_SMI_ENABLED
139};
140
136/*The flag indicates that the slave should delay the RESET cmd*/ 141/*The flag indicates that the slave should delay the RESET cmd*/
137#define MLX4_DELAY_RESET_SLAVE 0xbbbbbbb 142#define MLX4_DELAY_RESET_SLAVE 0xbbbbbbb
138/*indicates how many retries will be done if we are in the middle of FLR*/ 143/*indicates how many retries will be done if we are in the middle of FLR*/
@@ -488,6 +493,7 @@ struct mlx4_vport_state {
488 493
489struct mlx4_vf_admin_state { 494struct mlx4_vf_admin_state {
490 struct mlx4_vport_state vport[MLX4_MAX_PORTS + 1]; 495 struct mlx4_vport_state vport[MLX4_MAX_PORTS + 1];
496 u8 enable_smi[MLX4_MAX_PORTS + 1];
491}; 497};
492 498
493struct mlx4_vport_oper_state { 499struct mlx4_vport_oper_state {
@@ -495,8 +501,10 @@ struct mlx4_vport_oper_state {
495 int mac_idx; 501 int mac_idx;
496 int vlan_idx; 502 int vlan_idx;
497}; 503};
504
498struct mlx4_vf_oper_state { 505struct mlx4_vf_oper_state {
499 struct mlx4_vport_oper_state vport[MLX4_MAX_PORTS + 1]; 506 struct mlx4_vport_oper_state vport[MLX4_MAX_PORTS + 1];
507 u8 smi_enabled[MLX4_MAX_PORTS + 1];
500}; 508};
501 509
502struct slave_list { 510struct slave_list {
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 1c3fdd4a1f7d..ad98162a8d79 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -2827,10 +2827,12 @@ static int get_containing_mtt(struct mlx4_dev *dev, int slave, int start,
2827} 2827}
2828 2828
2829static int verify_qp_parameters(struct mlx4_dev *dev, 2829static int verify_qp_parameters(struct mlx4_dev *dev,
2830 struct mlx4_vhcr *vhcr,
2830 struct mlx4_cmd_mailbox *inbox, 2831 struct mlx4_cmd_mailbox *inbox,
2831 enum qp_transition transition, u8 slave) 2832 enum qp_transition transition, u8 slave)
2832{ 2833{
2833 u32 qp_type; 2834 u32 qp_type;
2835 u32 qpn;
2834 struct mlx4_qp_context *qp_ctx; 2836 struct mlx4_qp_context *qp_ctx;
2835 enum mlx4_qp_optpar optpar; 2837 enum mlx4_qp_optpar optpar;
2836 int port; 2838 int port;
@@ -2870,6 +2872,20 @@ static int verify_qp_parameters(struct mlx4_dev *dev,
2870 return -EINVAL; 2872 return -EINVAL;
2871 } 2873 }
2872 break; 2874 break;
2875 case MLX4_QP_ST_MLX:
2876 qpn = vhcr->in_modifier & 0x7fffff;
2877 port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;
2878 if (transition == QP_TRANS_INIT2RTR &&
2879 slave != mlx4_master_func_num(dev) &&
2880 mlx4_is_qp_reserved(dev, qpn) &&
2881 !mlx4_vf_smi_enabled(dev, slave, port)) {
2882 /* only enabled VFs may create MLX proxy QPs */
2883 mlx4_err(dev, "%s: unprivileged slave %d attempting to create an MLX proxy special QP on port %d\n",
2884 __func__, slave, port);
2885 return -EPERM;
2886 }
2887 break;
2888
2873 default: 2889 default:
2874 break; 2890 break;
2875 } 2891 }
@@ -3454,7 +3470,7 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
3454 err = adjust_qp_sched_queue(dev, slave, qpc, inbox); 3470 err = adjust_qp_sched_queue(dev, slave, qpc, inbox);
3455 if (err) 3471 if (err)
3456 return err; 3472 return err;
3457 err = verify_qp_parameters(dev, inbox, QP_TRANS_INIT2RTR, slave); 3473 err = verify_qp_parameters(dev, vhcr, inbox, QP_TRANS_INIT2RTR, slave);
3458 if (err) 3474 if (err)
3459 return err; 3475 return err;
3460 3476
@@ -3508,7 +3524,7 @@ int mlx4_RTR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
3508 err = adjust_qp_sched_queue(dev, slave, context, inbox); 3524 err = adjust_qp_sched_queue(dev, slave, context, inbox);
3509 if (err) 3525 if (err)
3510 return err; 3526 return err;
3511 err = verify_qp_parameters(dev, inbox, QP_TRANS_RTR2RTS, slave); 3527 err = verify_qp_parameters(dev, vhcr, inbox, QP_TRANS_RTR2RTS, slave);
3512 if (err) 3528 if (err)
3513 return err; 3529 return err;
3514 3530
@@ -3530,7 +3546,7 @@ int mlx4_RTS2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
3530 err = adjust_qp_sched_queue(dev, slave, context, inbox); 3546 err = adjust_qp_sched_queue(dev, slave, context, inbox);
3531 if (err) 3547 if (err)
3532 return err; 3548 return err;
3533 err = verify_qp_parameters(dev, inbox, QP_TRANS_RTS2RTS, slave); 3549 err = verify_qp_parameters(dev, vhcr, inbox, QP_TRANS_RTS2RTS, slave);
3534 if (err) 3550 if (err)
3535 return err; 3551 return err;
3536 3552
@@ -3567,7 +3583,7 @@ int mlx4_SQD2SQD_QP_wrapper(struct mlx4_dev *dev, int slave,
3567 err = adjust_qp_sched_queue(dev, slave, context, inbox); 3583 err = adjust_qp_sched_queue(dev, slave, context, inbox);
3568 if (err) 3584 if (err)
3569 return err; 3585 return err;
3570 err = verify_qp_parameters(dev, inbox, QP_TRANS_SQD2SQD, slave); 3586 err = verify_qp_parameters(dev, vhcr, inbox, QP_TRANS_SQD2SQD, slave);
3571 if (err) 3587 if (err)
3572 return err; 3588 return err;
3573 3589
@@ -3589,7 +3605,7 @@ int mlx4_SQD2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
3589 err = adjust_qp_sched_queue(dev, slave, context, inbox); 3605 err = adjust_qp_sched_queue(dev, slave, context, inbox);
3590 if (err) 3606 if (err)
3591 return err; 3607 return err;
3592 err = verify_qp_parameters(dev, inbox, QP_TRANS_SQD2RTS, slave); 3608 err = verify_qp_parameters(dev, vhcr, inbox, QP_TRANS_SQD2RTS, slave);
3593 if (err) 3609 if (err)
3594 return err; 3610 return err;
3595 3611
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 83612faa819c..e2fc7011314c 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -401,6 +401,7 @@ struct mlx4_caps {
401 int max_rq_desc_sz; 401 int max_rq_desc_sz;
402 int max_qp_init_rdma; 402 int max_qp_init_rdma;
403 int max_qp_dest_rdma; 403 int max_qp_dest_rdma;
404 u32 *qp0_qkey;
404 u32 *qp0_proxy; 405 u32 *qp0_proxy;
405 u32 *qp1_proxy; 406 u32 *qp1_proxy;
406 u32 *qp0_tunnel; 407 u32 *qp0_tunnel;