Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/806580/?format=api
{ "id": 806580, "url": "http://patchwork.ozlabs.org/api/patches/806580/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/1503927503-29065-2-git-send-email-tariqt@mellanox.com/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "name": "Linux network development", "link_name": "netdev", "list_id": "netdev.vger.kernel.org", "list_email": "netdev@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<1503927503-29065-2-git-send-email-tariqt@mellanox.com>", "list_archive_url": null, "date": "2017-08-28T13:38:20", "name": "[net-next,1/4] net/mlx4_core: Dynamically allocate structs at mlx4_slave_cap", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": true, "hash": "b751dfb3610a48d8f7e67f718e0af417aed114cc", "submitter": { "id": 68926, "url": "http://patchwork.ozlabs.org/api/people/68926/?format=api", "name": "Tariq Toukan", "email": "tariqt@mellanox.com" }, "delegate": { "id": 34, "url": "http://patchwork.ozlabs.org/api/users/34/?format=api", "username": "davem", "first_name": "David", "last_name": "Miller", "email": "davem@davemloft.net" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/1503927503-29065-2-git-send-email-tariqt@mellanox.com/mbox/", "series": [ { "id": 170, "url": "http://patchwork.ozlabs.org/api/series/170/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=170", "date": "2017-08-28T13:38:21", "name": "mlx4 misc patches", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/170/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/806580/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/806580/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming@ozlabs.org", "Delivered-To": "patchwork-incoming@ozlabs.org", "Authentication-Results": "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)", "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xgtD45HrWz9sNq\n\tfor <patchwork-incoming@ozlabs.org>;\n\tMon, 28 Aug 2017 23:39:32 +1000 (AEST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751304AbdH1NjW (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tMon, 28 Aug 2017 09:39:22 -0400", "from mail-il-dmz.mellanox.com ([193.47.165.129]:38608 \"EHLO\n\tmellanox.co.il\" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org\n\twith ESMTP id S1751209AbdH1NjM (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Mon, 28 Aug 2017 09:39:12 -0400", "from Internal Mail-Server by MTLPINE1 (envelope-from\n\ttariqt@mellanox.com)\n\twith ESMTPS (AES256-SHA encrypted); 28 Aug 2017 16:39:08 +0300", "from dev-l-vrt-206-006.mtl.labs.mlnx\n\t(dev-l-vrt-206-006.mtl.labs.mlnx [10.134.206.6])\n\tby labmailer.mlnx (8.13.8/8.13.8) with ESMTP id v7SDd79G014764;\n\tMon, 28 Aug 2017 16:39:07 +0300" ], "From": "Tariq Toukan <tariqt@mellanox.com>", "To": "\"David S. Miller\" <davem@davemloft.net>", "Cc": "netdev@vger.kernel.org, Eran Ben Elisha <eranbe@mellanox.com>,\n\tTal Alon <talal@mellanox.com>, Tariq Toukan <tariqt@mellanox.com>,\n\tSaeed Mahameed <saeedm@mellanox.com>", "Subject": "[PATCH net-next 1/4] net/mlx4_core: Dynamically allocate structs at\n\tmlx4_slave_cap", "Date": "Mon, 28 Aug 2017 16:38:20 +0300", "Message-Id": "<1503927503-29065-2-git-send-email-tariqt@mellanox.com>", "X-Mailer": "git-send-email 1.8.3.1", "In-Reply-To": "<1503927503-29065-1-git-send-email-tariqt@mellanox.com>", "References": "<1503927503-29065-1-git-send-email-tariqt@mellanox.com>", "Sender": "netdev-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "From: Eran Ben Elisha <eranbe@mellanox.com>\n\nIn order to avoid temporary large structs on the stack,\nallocate them dynamically.\n\nSigned-off-by: Eran Ben Elisha <eranbe@mellanox.com>\nSigned-off-by: Tal Alon <talal@mellanox.com>\nSigned-off-by: Tariq Toukan <tariqt@mellanox.com>\nSigned-off-by: Saeed Mahameed <saeedm@mellanox.com>\n---\n drivers/infiniband/hw/mlx4/qp.c | 26 ++--\n drivers/net/ethernet/mellanox/mlx4/fw.c | 12 +-\n drivers/net/ethernet/mellanox/mlx4/fw.h | 6 +-\n drivers/net/ethernet/mellanox/mlx4/main.c | 235 ++++++++++++++++--------------\n drivers/net/ethernet/mellanox/mlx4/qp.c | 24 +--\n include/linux/mlx4/device.h | 14 +-\n 6 files changed, 159 insertions(+), 158 deletions(-)", "diff": "diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c\nindex 75c0e6c5dd56..83e5c72f19b8 100644\n--- a/drivers/infiniband/hw/mlx4/qp.c\n+++ b/drivers/infiniband/hw/mlx4/qp.c\n@@ -145,8 +145,8 @@ static int is_sqp(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)\n \t/* VF or PF -- proxy SQP */\n \tif (mlx4_is_mfunc(dev->dev)) {\n \t\tfor (i = 0; i < dev->dev->caps.num_ports; i++) {\n-\t\t\tif (qp->mqp.qpn == dev->dev->caps.qp0_proxy[i] ||\n-\t\t\t qp->mqp.qpn == dev->dev->caps.qp1_proxy[i]) {\n+\t\t\tif (qp->mqp.qpn == dev->dev->caps.spec_qps[i].qp0_proxy ||\n+\t\t\t qp->mqp.qpn == dev->dev->caps.spec_qps[i].qp1_proxy) {\n \t\t\t\tproxy_sqp = 1;\n \t\t\t\tbreak;\n \t\t\t}\n@@ -173,7 +173,7 @@ static int is_qp0(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)\n \t/* VF or PF -- proxy QP0 */\n \tif (mlx4_is_mfunc(dev->dev)) {\n \t\tfor (i = 0; i < dev->dev->caps.num_ports; i++) {\n-\t\t\tif (qp->mqp.qpn == dev->dev->caps.qp0_proxy[i]) {\n+\t\t\tif (qp->mqp.qpn == dev->dev->caps.spec_qps[i].qp0_proxy) {\n \t\t\t\tproxy_qp0 = 1;\n \t\t\t\tbreak;\n \t\t\t}\n@@ -614,8 +614,8 @@ static int qp0_enabled_vf(struct mlx4_dev *dev, int qpn)\n {\n \tint i;\n \tfor (i = 0; i < dev->caps.num_ports; i++) {\n-\t\tif (qpn == dev->caps.qp0_proxy[i])\n-\t\t\treturn !!dev->caps.qp0_qkey[i];\n+\t\tif (qpn == dev->caps.spec_qps[i].qp0_proxy)\n+\t\t\treturn !!dev->caps.spec_qps[i].qp0_qkey;\n \t}\n \treturn 0;\n }\n@@ -1114,9 +1114,9 @@ static u32 get_sqp_num(struct mlx4_ib_dev *dev, struct ib_qp_init_attr *attr)\n \t}\n \t/* PF or VF -- creating proxies */\n \tif (attr->qp_type == IB_QPT_SMI)\n-\t\treturn dev->dev->caps.qp0_proxy[attr->port_num - 1];\n+\t\treturn dev->dev->caps.spec_qps[attr->port_num - 1].qp0_proxy;\n \telse\n-\t\treturn dev->dev->caps.qp1_proxy[attr->port_num - 1];\n+\t\treturn dev->dev->caps.spec_qps[attr->port_num - 1].qp1_proxy;\n }\n \n static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd,\n@@ -2277,9 +2277,9 @@ static int vf_get_qp0_qkey(struct mlx4_dev *dev, int qpn, u32 *qkey)\n {\n \tint i;\n \tfor (i = 0; i < dev->caps.num_ports; i++) {\n-\t\tif (qpn == dev->caps.qp0_proxy[i] ||\n-\t\t qpn == dev->caps.qp0_tunnel[i]) {\n-\t\t\t*qkey = dev->caps.qp0_qkey[i];\n+\t\tif (qpn == dev->caps.spec_qps[i].qp0_proxy ||\n+\t\t qpn == dev->caps.spec_qps[i].qp0_tunnel) {\n+\t\t\t*qkey = dev->caps.spec_qps[i].qp0_qkey;\n \t\t\treturn 0;\n \t\t}\n \t}\n@@ -2340,7 +2340,7 @@ static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp,\n \t\tsqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);\n \telse\n \t\tsqp->ud_header.bth.destination_qpn =\n-\t\t\tcpu_to_be32(mdev->dev->caps.qp0_tunnel[sqp->qp.port - 1]);\n+\t\t\tcpu_to_be32(mdev->dev->caps.spec_qps[sqp->qp.port - 1].qp0_tunnel);\n \n \tsqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));\n \tif (mlx4_is_master(mdev->dev)) {\n@@ -2800,9 +2800,9 @@ static void set_tunnel_datagram_seg(struct mlx4_ib_dev *dev,\n \n \tmemcpy(dseg->av, &sqp_av, sizeof (struct mlx4_av));\n \tif (qpt == MLX4_IB_QPT_PROXY_GSI)\n-\t\tdseg->dqpn = cpu_to_be32(dev->dev->caps.qp1_tunnel[port - 1]);\n+\t\tdseg->dqpn = cpu_to_be32(dev->dev->caps.spec_qps[port - 1].qp1_tunnel);\n \telse\n-\t\tdseg->dqpn = cpu_to_be32(dev->dev->caps.qp0_tunnel[port - 1]);\n+\t\tdseg->dqpn = cpu_to_be32(dev->dev->caps.spec_qps[port - 1].qp0_tunnel);\n \t/* Use QKEY from the QP context, which is set by master */\n \tdseg->qkey = cpu_to_be32(IB_QP_SET_QKEY);\n }\ndiff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c\nindex 042707623922..f76cac01d564 100644\n--- a/drivers/net/ethernet/mellanox/mlx4/fw.c\n+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c\n@@ -679,22 +679,22 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port,\n \n \tif (func_cap->flags1 & QUERY_FUNC_CAP_VF_ENABLE_QP0) {\n \t\tMLX4_GET(qkey, outbox, QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET);\n-\t\tfunc_cap->qp0_qkey = qkey;\n+\t\tfunc_cap->spec_qps.qp0_qkey = qkey;\n \t} else {\n-\t\tfunc_cap->qp0_qkey = 0;\n+\t\tfunc_cap->spec_qps.qp0_qkey = 0;\n \t}\n \n \tMLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_TUNNEL);\n-\tfunc_cap->qp0_tunnel_qpn = size & 0xFFFFFF;\n+\tfunc_cap->spec_qps.qp0_tunnel = size & 0xFFFFFF;\n \n \tMLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_PROXY);\n-\tfunc_cap->qp0_proxy_qpn = size & 0xFFFFFF;\n+\tfunc_cap->spec_qps.qp0_proxy = size & 0xFFFFFF;\n \n \tMLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_TUNNEL);\n-\tfunc_cap->qp1_tunnel_qpn = size & 0xFFFFFF;\n+\tfunc_cap->spec_qps.qp1_tunnel = size & 0xFFFFFF;\n \n \tMLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_PROXY);\n-\tfunc_cap->qp1_proxy_qpn = size & 0xFFFFFF;\n+\tfunc_cap->spec_qps.qp1_proxy = size & 0xFFFFFF;\n \n \tif (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_NIC_INFO)\n \t\tMLX4_GET(func_cap->phys_port_id, outbox,\ndiff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h\nindex b52ba01aa486..cd6399c76bfd 100644\n--- a/drivers/net/ethernet/mellanox/mlx4/fw.h\n+++ b/drivers/net/ethernet/mellanox/mlx4/fw.h\n@@ -144,11 +144,7 @@ struct mlx4_func_cap {\n \tint\tmax_eq;\n \tint\treserved_eq;\n \tint\tmcg_quota;\n-\tu32\tqp0_qkey;\n-\tu32\tqp0_tunnel_qpn;\n-\tu32\tqp0_proxy_qpn;\n-\tu32\tqp1_tunnel_qpn;\n-\tu32\tqp1_proxy_qpn;\n+\tstruct mlx4_spec_qps spec_qps;\n \tu32\treserved_lkey;\n \tu8\tphysical_port;\n \tu8\tflags0;\ndiff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c\nindex 8404e165eca4..e6413a8a5f07 100644\n--- a/drivers/net/ethernet/mellanox/mlx4/main.c\n+++ b/drivers/net/ethernet/mellanox/mlx4/main.c\n@@ -819,38 +819,93 @@ static void slave_adjust_steering_mode(struct mlx4_dev *dev,\n \t\t mlx4_steering_mode_str(dev->caps.steering_mode));\n }\n \n+static void mlx4_slave_destroy_special_qp_cap(struct mlx4_dev *dev)\n+{\n+\tkfree(dev->caps.spec_qps);\n+\tdev->caps.spec_qps = NULL;\n+}\n+\n+static int mlx4_slave_special_qp_cap(struct mlx4_dev *dev)\n+{\n+\tstruct mlx4_func_cap *func_cap = NULL;\n+\tstruct mlx4_caps *caps = &dev->caps;\n+\tint i, err = 0;\n+\n+\tfunc_cap = kzalloc(sizeof(*func_cap), GFP_KERNEL);\n+\tcaps->spec_qps = kcalloc(caps->num_ports, sizeof(*caps->spec_qps), GFP_KERNEL);\n+\n+\tif (!func_cap || !caps->spec_qps) {\n+\t\tmlx4_err(dev, \"Failed to allocate memory for special qps cap\\n\");\n+\t\terr = -ENOMEM;\n+\t\tgoto err_mem;\n+\t}\n+\n+\tfor (i = 1; i <= caps->num_ports; ++i) {\n+\t\terr = mlx4_QUERY_FUNC_CAP(dev, i, func_cap);\n+\t\tif (err) {\n+\t\t\tmlx4_err(dev, \"QUERY_FUNC_CAP port command failed for port %d, aborting (%d)\\n\",\n+\t\t\t\t i, err);\n+\t\t\tgoto err_mem;\n+\t\t}\n+\t\tcaps->spec_qps[i - 1] = func_cap->spec_qps;\n+\t\tcaps->port_mask[i] = caps->port_type[i];\n+\t\tcaps->phys_port_id[i] = func_cap->phys_port_id;\n+\t\terr = mlx4_get_slave_pkey_gid_tbl_len(dev, i,\n+\t\t\t\t\t\t &caps->gid_table_len[i],\n+\t\t\t\t\t\t &caps->pkey_table_len[i]);\n+\t\tif (err) {\n+\t\t\tmlx4_err(dev, \"QUERY_PORT command failed for port %d, aborting (%d)\\n\",\n+\t\t\t\t i, err);\n+\t\t\tgoto err_mem;\n+\t\t}\n+\t}\n+\n+err_mem:\n+\tif (err)\n+\t\tmlx4_slave_destroy_special_qp_cap(dev);\n+\tkfree(func_cap);\n+\treturn err;\n+}\n+\n static int mlx4_slave_cap(struct mlx4_dev *dev)\n {\n \tint\t\t\t err;\n \tu32\t\t\t page_size;\n-\tstruct mlx4_dev_cap\t dev_cap;\n-\tstruct mlx4_func_cap\t func_cap;\n-\tstruct mlx4_init_hca_param hca_param;\n-\tu8\t\t\t i;\n+\tstruct mlx4_dev_cap\t *dev_cap = NULL;\n+\tstruct mlx4_func_cap\t *func_cap = NULL;\n+\tstruct mlx4_init_hca_param *hca_param = NULL;\n+\n+\thca_param = kzalloc(sizeof(*hca_param), GFP_KERNEL);\n+\tfunc_cap = kzalloc(sizeof(*func_cap), GFP_KERNEL);\n+\tdev_cap = kzalloc(sizeof(*dev_cap), GFP_KERNEL);\n+\tif (!hca_param || !func_cap || !dev_cap) {\n+\t\tmlx4_err(dev, \"Failed to allocate memory for slave_cap\\n\");\n+\t\terr = -ENOMEM;\n+\t\tgoto free_mem;\n+\t}\n \n-\tmemset(&hca_param, 0, sizeof(hca_param));\n-\terr = mlx4_QUERY_HCA(dev, &hca_param);\n+\terr = mlx4_QUERY_HCA(dev, hca_param);\n \tif (err) {\n \t\tmlx4_err(dev, \"QUERY_HCA command failed, aborting\\n\");\n-\t\treturn err;\n+\t\tgoto free_mem;\n \t}\n \n \t/* fail if the hca has an unknown global capability\n \t * at this time global_caps should be always zeroed\n \t */\n-\tif (hca_param.global_caps) {\n+\tif (hca_param->global_caps) {\n \t\tmlx4_err(dev, \"Unknown hca global capabilities\\n\");\n-\t\treturn -EINVAL;\n+\t\terr = -EINVAL;\n+\t\tgoto free_mem;\n \t}\n \n-\tdev->caps.hca_core_clock = hca_param.hca_core_clock;\n+\tdev->caps.hca_core_clock = hca_param->hca_core_clock;\n \n-\tmemset(&dev_cap, 0, sizeof(dev_cap));\n-\tdev->caps.max_qp_dest_rdma = 1 << hca_param.log_rd_per_qp;\n-\terr = mlx4_dev_cap(dev, &dev_cap);\n+\tdev->caps.max_qp_dest_rdma = 1 << hca_param->log_rd_per_qp;\n+\terr = mlx4_dev_cap(dev, dev_cap);\n \tif (err) {\n \t\tmlx4_err(dev, \"QUERY_DEV_CAP command failed, aborting\\n\");\n-\t\treturn err;\n+\t\tgoto free_mem;\n \t}\n \n \terr = mlx4_QUERY_FW(dev);\n@@ -862,21 +917,23 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)\n \tif (page_size > PAGE_SIZE) {\n \t\tmlx4_err(dev, \"HCA minimum page size of %d bigger than kernel PAGE_SIZE of %ld, aborting\\n\",\n \t\t\t page_size, PAGE_SIZE);\n-\t\treturn -ENODEV;\n+\t\terr = -ENODEV;\n+\t\tgoto free_mem;\n \t}\n \n \t/* Set uar_page_shift for VF */\n-\tdev->uar_page_shift = hca_param.uar_page_sz + 12;\n+\tdev->uar_page_shift = hca_param->uar_page_sz + 12;\n \n \t/* Make sure the master uar page size is valid */\n \tif (dev->uar_page_shift > PAGE_SHIFT) {\n \t\tmlx4_err(dev,\n \t\t\t \"Invalid configuration: uar page size is larger than system page size\\n\");\n-\t\treturn -ENODEV;\n+\t\terr = -ENODEV;\n+\t\tgoto free_mem;\n \t}\n \n \t/* Set reserved_uars based on the uar_page_shift */\n-\tmlx4_set_num_reserved_uars(dev, &dev_cap);\n+\tmlx4_set_num_reserved_uars(dev, dev_cap);\n \n \t/* Although uar page size in FW differs from system page size,\n \t * upper software layers (mlx4_ib, mlx4_en and part of mlx4_core)\n@@ -884,34 +941,35 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)\n \t */\n \tdev->caps.uar_page_size = PAGE_SIZE;\n \n-\tmemset(&func_cap, 0, sizeof(func_cap));\n-\terr = mlx4_QUERY_FUNC_CAP(dev, 0, &func_cap);\n+\terr = mlx4_QUERY_FUNC_CAP(dev, 0, func_cap);\n \tif (err) {\n \t\tmlx4_err(dev, \"QUERY_FUNC_CAP general command failed, aborting (%d)\\n\",\n \t\t\t err);\n-\t\treturn err;\n+\t\tgoto free_mem;\n \t}\n \n-\tif ((func_cap.pf_context_behaviour | PF_CONTEXT_BEHAVIOUR_MASK) !=\n+\tif ((func_cap->pf_context_behaviour | PF_CONTEXT_BEHAVIOUR_MASK) !=\n \t PF_CONTEXT_BEHAVIOUR_MASK) {\n \t\tmlx4_err(dev, \"Unknown pf context behaviour %x known flags %x\\n\",\n-\t\t\t func_cap.pf_context_behaviour, PF_CONTEXT_BEHAVIOUR_MASK);\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tdev->caps.num_ports\t\t= func_cap.num_ports;\n-\tdev->quotas.qp\t\t\t= func_cap.qp_quota;\n-\tdev->quotas.srq\t\t\t= func_cap.srq_quota;\n-\tdev->quotas.cq\t\t\t= func_cap.cq_quota;\n-\tdev->quotas.mpt\t\t\t= func_cap.mpt_quota;\n-\tdev->quotas.mtt\t\t\t= func_cap.mtt_quota;\n-\tdev->caps.num_qps\t\t= 1 << hca_param.log_num_qps;\n-\tdev->caps.num_srqs\t\t= 1 << hca_param.log_num_srqs;\n-\tdev->caps.num_cqs\t\t= 1 << hca_param.log_num_cqs;\n-\tdev->caps.num_mpts\t\t= 1 << hca_param.log_mpt_sz;\n-\tdev->caps.num_eqs\t\t= func_cap.max_eq;\n-\tdev->caps.reserved_eqs\t\t= func_cap.reserved_eq;\n-\tdev->caps.reserved_lkey\t\t= func_cap.reserved_lkey;\n+\t\t\t func_cap->pf_context_behaviour,\n+\t\t\t PF_CONTEXT_BEHAVIOUR_MASK);\n+\t\terr = -EINVAL;\n+\t\tgoto free_mem;\n+\t}\n+\n+\tdev->caps.num_ports\t\t= func_cap->num_ports;\n+\tdev->quotas.qp\t\t\t= func_cap->qp_quota;\n+\tdev->quotas.srq\t\t\t= func_cap->srq_quota;\n+\tdev->quotas.cq\t\t\t= func_cap->cq_quota;\n+\tdev->quotas.mpt\t\t\t= func_cap->mpt_quota;\n+\tdev->quotas.mtt\t\t\t= func_cap->mtt_quota;\n+\tdev->caps.num_qps\t\t= 1 << hca_param->log_num_qps;\n+\tdev->caps.num_srqs\t\t= 1 << hca_param->log_num_srqs;\n+\tdev->caps.num_cqs\t\t= 1 << hca_param->log_num_cqs;\n+\tdev->caps.num_mpts\t\t= 1 << hca_param->log_mpt_sz;\n+\tdev->caps.num_eqs\t\t= func_cap->max_eq;\n+\tdev->caps.reserved_eqs\t\t= func_cap->reserved_eq;\n+\tdev->caps.reserved_lkey\t\t= func_cap->reserved_lkey;\n \tdev->caps.num_pds = MLX4_NUM_PDS;\n \tdev->caps.num_mgms = 0;\n \tdev->caps.num_amgms = 0;\n@@ -924,38 +982,10 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)\n \n \tmlx4_replace_zero_macs(dev);\n \n-\tdev->caps.qp0_qkey = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);\n-\tdev->caps.qp0_tunnel = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);\n-\tdev->caps.qp0_proxy = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);\n-\tdev->caps.qp1_tunnel = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);\n-\tdev->caps.qp1_proxy = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);\n-\n-\tif (!dev->caps.qp0_tunnel || !dev->caps.qp0_proxy ||\n-\t !dev->caps.qp1_tunnel || !dev->caps.qp1_proxy ||\n-\t !dev->caps.qp0_qkey) {\n-\t\terr = -ENOMEM;\n-\t\tgoto err_mem;\n-\t}\n-\n-\tfor (i = 1; i <= dev->caps.num_ports; ++i) {\n-\t\terr = mlx4_QUERY_FUNC_CAP(dev, i, &func_cap);\n-\t\tif (err) {\n-\t\t\tmlx4_err(dev, \"QUERY_FUNC_CAP port command failed for port %d, aborting (%d)\\n\",\n-\t\t\t\t i, err);\n-\t\t\tgoto err_mem;\n-\t\t}\n-\t\tdev->caps.qp0_qkey[i - 1] = func_cap.qp0_qkey;\n-\t\tdev->caps.qp0_tunnel[i - 1] = func_cap.qp0_tunnel_qpn;\n-\t\tdev->caps.qp0_proxy[i - 1] = func_cap.qp0_proxy_qpn;\n-\t\tdev->caps.qp1_tunnel[i - 1] = func_cap.qp1_tunnel_qpn;\n-\t\tdev->caps.qp1_proxy[i - 1] = func_cap.qp1_proxy_qpn;\n-\t\tdev->caps.port_mask[i] = dev->caps.port_type[i];\n-\t\tdev->caps.phys_port_id[i] = func_cap.phys_port_id;\n-\t\terr = mlx4_get_slave_pkey_gid_tbl_len(dev, i,\n-\t\t\t\t\t\t &dev->caps.gid_table_len[i],\n-\t\t\t\t\t\t &dev->caps.pkey_table_len[i]);\n-\t\tif (err)\n-\t\t\tgoto err_mem;\n+\terr = mlx4_slave_special_qp_cap(dev);\n+\tif (err) {\n+\t\tmlx4_err(dev, \"Set special QP caps failed. aborting\\n\");\n+\t\tgoto free_mem;\n \t}\n \n \tif (dev->caps.uar_page_size * (dev->caps.num_uars -\n@@ -970,7 +1000,7 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)\n \t\tgoto err_mem;\n \t}\n \n-\tif (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_EQE_ENABLED) {\n+\tif (hca_param->dev_cap_enabled & MLX4_DEV_CAP_64B_EQE_ENABLED) {\n \t\tdev->caps.eqe_size = 64;\n \t\tdev->caps.eqe_factor = 1;\n \t} else {\n@@ -978,20 +1008,20 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)\n \t\tdev->caps.eqe_factor = 0;\n \t}\n \n-\tif (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_CQE_ENABLED) {\n+\tif (hca_param->dev_cap_enabled & MLX4_DEV_CAP_64B_CQE_ENABLED) {\n \t\tdev->caps.cqe_size = 64;\n \t\tdev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE;\n \t} else {\n \t\tdev->caps.cqe_size = 32;\n \t}\n \n-\tif (hca_param.dev_cap_enabled & MLX4_DEV_CAP_EQE_STRIDE_ENABLED) {\n-\t\tdev->caps.eqe_size = hca_param.eqe_size;\n+\tif (hca_param->dev_cap_enabled & MLX4_DEV_CAP_EQE_STRIDE_ENABLED) {\n+\t\tdev->caps.eqe_size = hca_param->eqe_size;\n \t\tdev->caps.eqe_factor = 0;\n \t}\n \n-\tif (hca_param.dev_cap_enabled & MLX4_DEV_CAP_CQE_STRIDE_ENABLED) {\n-\t\tdev->caps.cqe_size = hca_param.cqe_size;\n+\tif (hca_param->dev_cap_enabled & MLX4_DEV_CAP_CQE_STRIDE_ENABLED) {\n+\t\tdev->caps.cqe_size = hca_param->cqe_size;\n \t\t/* User still need to know when CQE > 32B */\n \t\tdev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE;\n \t}\n@@ -999,31 +1029,24 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)\n \tdev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;\n \tmlx4_warn(dev, \"Timestamping is not supported in slave mode\\n\");\n \n-\tslave_adjust_steering_mode(dev, &dev_cap, &hca_param);\n+\tslave_adjust_steering_mode(dev, dev_cap, hca_param);\n \tmlx4_dbg(dev, \"RSS support for IP fragments is %s\\n\",\n-\t\t hca_param.rss_ip_frags ? \"on\" : \"off\");\n+\t\t hca_param->rss_ip_frags ? \"on\" : \"off\");\n \n-\tif (func_cap.extra_flags & MLX4_QUERY_FUNC_FLAGS_BF_RES_QP &&\n+\tif (func_cap->extra_flags & MLX4_QUERY_FUNC_FLAGS_BF_RES_QP &&\n \t dev->caps.bf_reg_size)\n \t\tdev->caps.alloc_res_qp_mask |= MLX4_RESERVE_ETH_BF_QP;\n \n-\tif (func_cap.extra_flags & MLX4_QUERY_FUNC_FLAGS_A0_RES_QP)\n+\tif (func_cap->extra_flags & MLX4_QUERY_FUNC_FLAGS_A0_RES_QP)\n \t\tdev->caps.alloc_res_qp_mask |= MLX4_RESERVE_A0_QP;\n \n-\treturn 0;\n-\n err_mem:\n-\tkfree(dev->caps.qp0_qkey);\n-\tkfree(dev->caps.qp0_tunnel);\n-\tkfree(dev->caps.qp0_proxy);\n-\tkfree(dev->caps.qp1_tunnel);\n-\tkfree(dev->caps.qp1_proxy);\n-\tdev->caps.qp0_qkey = NULL;\n-\tdev->caps.qp0_tunnel = NULL;\n-\tdev->caps.qp0_proxy = NULL;\n-\tdev->caps.qp1_tunnel = NULL;\n-\tdev->caps.qp1_proxy = NULL;\n-\n+\tif (err)\n+\t\tmlx4_slave_destroy_special_qp_cap(dev);\n+free_mem:\n+\tkfree(hca_param);\n+\tkfree(func_cap);\n+\tkfree(dev_cap);\n \treturn err;\n }\n \n@@ -2407,13 +2430,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev)\n \tunmap_internal_clock(dev);\n \tunmap_bf_area(dev);\n \n-\tif (mlx4_is_slave(dev)) {\n-\t\tkfree(dev->caps.qp0_qkey);\n-\t\tkfree(dev->caps.qp0_tunnel);\n-\t\tkfree(dev->caps.qp0_proxy);\n-\t\tkfree(dev->caps.qp1_tunnel);\n-\t\tkfree(dev->caps.qp1_proxy);\n-\t}\n+\tif (mlx4_is_slave(dev))\n+\t\tmlx4_slave_destroy_special_qp_cap(dev);\n \n err_close:\n \tif (mlx4_is_slave(dev))\n@@ -3596,13 +3614,8 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data,\n \t\tmlx4_multi_func_cleanup(dev);\n \t}\n \n-\tif (mlx4_is_slave(dev)) {\n-\t\tkfree(dev->caps.qp0_qkey);\n-\t\tkfree(dev->caps.qp0_tunnel);\n-\t\tkfree(dev->caps.qp0_proxy);\n-\t\tkfree(dev->caps.qp1_tunnel);\n-\t\tkfree(dev->caps.qp1_proxy);\n-\t}\n+\tif (mlx4_is_slave(dev))\n+\t\tmlx4_slave_destroy_special_qp_cap(dev);\n \n err_close:\n \tmlx4_close_hca(dev);\n@@ -3942,11 +3955,7 @@ static void mlx4_unload_one(struct pci_dev *pdev)\n \tif (!mlx4_is_slave(dev))\n \t\tmlx4_free_ownership(dev);\n \n-\tkfree(dev->caps.qp0_qkey);\n-\tkfree(dev->caps.qp0_tunnel);\n-\tkfree(dev->caps.qp0_proxy);\n-\tkfree(dev->caps.qp1_tunnel);\n-\tkfree(dev->caps.qp1_proxy);\n+\tmlx4_slave_destroy_special_qp_cap(dev);\n \tkfree(dev->dev_vfs);\n \n \tmlx4_clean_dev(dev);\ndiff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c\nindex 2b067763a6bc..28c441c0d31f 100644\n--- a/drivers/net/ethernet/mellanox/mlx4/qp.c\n+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c\n@@ -844,24 +844,20 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)\n \n \t\t/* In mfunc, calculate proxy and tunnel qp offsets for the PF here,\n \t\t * since the PF does not call mlx4_slave_caps */\n-\t\tdev->caps.qp0_tunnel = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);\n-\t\tdev->caps.qp0_proxy = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);\n-\t\tdev->caps.qp1_tunnel = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);\n-\t\tdev->caps.qp1_proxy = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);\n+\t\tdev->caps.spec_qps = kcalloc(dev->caps.num_ports, sizeof(dev->caps.spec_qps), GFP_KERNEL);\n \n-\t\tif (!dev->caps.qp0_tunnel || !dev->caps.qp0_proxy ||\n-\t\t !dev->caps.qp1_tunnel || !dev->caps.qp1_proxy) {\n+\t\tif (!dev->caps.spec_qps) {\n \t\t\terr = -ENOMEM;\n \t\t\tgoto err_mem;\n \t\t}\n \n \t\tfor (k = 0; k < dev->caps.num_ports; k++) {\n-\t\t\tdev->caps.qp0_proxy[k] = dev->phys_caps.base_proxy_sqpn +\n+\t\t\tdev->caps.spec_qps[k].qp0_proxy = dev->phys_caps.base_proxy_sqpn +\n \t\t\t\t8 * mlx4_master_func_num(dev) + k;\n-\t\t\tdev->caps.qp0_tunnel[k] = dev->caps.qp0_proxy[k] + 8 * MLX4_MFUNC_MAX;\n-\t\t\tdev->caps.qp1_proxy[k] = dev->phys_caps.base_proxy_sqpn +\n+\t\t\tdev->caps.spec_qps[k].qp0_tunnel = dev->caps.spec_qps[k].qp0_proxy + 8 * MLX4_MFUNC_MAX;\n+\t\t\tdev->caps.spec_qps[k].qp1_proxy = dev->phys_caps.base_proxy_sqpn +\n \t\t\t\t8 * mlx4_master_func_num(dev) + MLX4_MAX_PORTS + k;\n-\t\t\tdev->caps.qp1_tunnel[k] = dev->caps.qp1_proxy[k] + 8 * MLX4_MFUNC_MAX;\n+\t\t\tdev->caps.spec_qps[k].qp1_tunnel = dev->caps.spec_qps[k].qp1_proxy + 8 * MLX4_MFUNC_MAX;\n \t\t}\n \t}\n \n@@ -873,12 +869,8 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)\n \treturn err;\n \n err_mem:\n-\tkfree(dev->caps.qp0_tunnel);\n-\tkfree(dev->caps.qp0_proxy);\n-\tkfree(dev->caps.qp1_tunnel);\n-\tkfree(dev->caps.qp1_proxy);\n-\tdev->caps.qp0_tunnel = dev->caps.qp0_proxy =\n-\t\tdev->caps.qp1_tunnel = dev->caps.qp1_proxy = NULL;\n+\tkfree(dev->caps.spec_qps);\n+\tdev->caps.spec_qps = NULL;\n \tmlx4_cleanup_qp_zones(dev);\n \treturn err;\n }\ndiff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h\nindex b54517c05e9a..9844606f9491 100644\n--- a/include/linux/mlx4/device.h\n+++ b/include/linux/mlx4/device.h\n@@ -518,6 +518,14 @@ struct mlx4_phys_caps {\n \tu32\t\t\tbase_tunnel_sqpn;\n };\n \n+struct mlx4_spec_qps {\n+\tu32 qp0_qkey;\n+\tu32 qp0_proxy;\n+\tu32 qp0_tunnel;\n+\tu32 qp1_proxy;\n+\tu32 qp1_tunnel;\n+};\n+\n struct mlx4_caps {\n \tu64\t\t\tfw_ver;\n \tu32\t\t\tfunction;\n@@ -547,11 +555,7 @@ struct mlx4_caps {\n \tint\t\t\tmax_qp_init_rdma;\n \tint\t\t\tmax_qp_dest_rdma;\n \tint\t\t\tmax_tc_eth;\n-\tu32\t\t\t*qp0_qkey;\n-\tu32\t\t\t*qp0_proxy;\n-\tu32\t\t\t*qp1_proxy;\n-\tu32\t\t\t*qp0_tunnel;\n-\tu32\t\t\t*qp1_tunnel;\n+\tstruct mlx4_spec_qps *spec_qps;\n \tint\t\t\tnum_srqs;\n \tint\t\t\tmax_srq_wqes;\n \tint\t\t\tmax_srq_sge;\n", "prefixes": [ "net-next", "1/4" ] }