diff options
| -rw-r--r-- | drivers/infiniband/hw/mlx4/qp.c | 52 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/cmd.c | 13 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.c | 44 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 16 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 8 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 26 | ||||
| -rw-r--r-- | include/linux/mlx4/device.h | 1 |
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 | ||
| 611 | static 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 | |||
| 611 | static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, | 621 | static 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 | ||
| 1948 | static 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 | |||
| 1933 | static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp, | 1961 | static 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 | ||
| 2554 | int mlx4_vf_smi_enabled(struct mlx4_dev *dev, int slave, int port) | 2558 | int 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 | } |
| 2558 | EXPORT_SYMBOL_GPL(mlx4_vf_smi_enabled); | 2569 | EXPORT_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 | ||
| 731 | err_mem: | 734 | err_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 | ||
| 136 | enum { | ||
| 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 | ||
| 489 | struct mlx4_vf_admin_state { | 494 | struct 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 | ||
| 493 | struct mlx4_vport_oper_state { | 499 | struct 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 | |||
| 498 | struct mlx4_vf_oper_state { | 505 | struct 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 | ||
| 502 | struct slave_list { | 510 | struct 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 | ||
| 2829 | static int verify_qp_parameters(struct mlx4_dev *dev, | 2829 | static 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; |
