From patchwork Tue Dec 20 09:13:21 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Selvin Xavier X-Patchwork-Id: 9481279 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B7AD7600CA for ; Tue, 20 Dec 2016 09:14:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9DFFB2846A for ; Tue, 20 Dec 2016 09:14:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 910D728476; Tue, 20 Dec 2016 09:14:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 69D8E2846A for ; Tue, 20 Dec 2016 09:14:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933737AbcLTJOk (ORCPT ); Tue, 20 Dec 2016 04:14:40 -0500 Received: from mail-qk0-f180.google.com ([209.85.220.180]:36652 "EHLO mail-qk0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933728AbcLTJOf (ORCPT ); Tue, 20 Dec 2016 04:14:35 -0500 Received: by mail-qk0-f180.google.com with SMTP id n21so36766576qka.3 for ; Tue, 20 Dec 2016 01:14:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=yFzCrukqpwOIFfDSI8Bm8Jksgd3bcAaXtoDXgXVMA1c=; b=emkjJ051hv7uJPkB96uJCCgdWdyvNFvAWtMc5TvRthD8NKK5MUH85T22j897B/rsY/ Q2M+hXKMhg45hkU+ZE1zyMlzGzMKkx4WNtBPjPjZEaxRle6vCmV3N9VsNCNyyUe12pr8 1ZUNdwM/ctc/psShNYV1GowD+1826o6lPrGrs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=yFzCrukqpwOIFfDSI8Bm8Jksgd3bcAaXtoDXgXVMA1c=; b=cWdY6gONvvYUIV0ThaILX9t0A90iudy2C1PeLrWm+WlAkKR0DKsN72l3L1kC55pGrf e0ubFrDswhZEiVjxCOSb3H6mniTtYQPOtT3K1dI1vkK6o7mx4lThWUJukVfmsPCuYo4H 8hxr8LERz8lNz+YEGTkmn1tmO9fbdXvC74tMUrj/YDej36KwZnFdv7GwE2JnDI5hM/c5 gmWIJeaM+1PDrF/tCiFBGiw4xU+c65TqQmMDo58d04iWiLVxM3dA4KRYSq7NARfq+/i4 Qm883spz3ypSyOIRh/X64dgaS7HxGkoGC+b4NO2hXeaEPRp2mjxPpx2/gfde9oEVATdN 9XbQ== X-Gm-Message-State: AIkVDXKx/I9+BhXnbiCgYGYr3huwzxrZl4C5p/WoFgk69+XmLPiy4WbI2RU8sip4M07MCfHs X-Received: by 10.55.36.204 with SMTP id k73mr5322069qkk.125.1482225274306; Tue, 20 Dec 2016 01:14:34 -0800 (PST) Received: from dhcp-10-192-206-197.iig.avagotech.net ([192.19.239.250]) by smtp.gmail.com with ESMTPSA id b63sm12494452qka.39.2016.12.20.01.14.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 20 Dec 2016 01:14:33 -0800 (PST) From: Selvin Xavier To: dledford@redhat.com, linux-rdma@vger.kernel.org Cc: netdev@vger.kernel.org, michael.chan@broadcom.com, Selvin Xavier , Eddie Wai , Devesh Sharma , Somnath Kotur , Sriharsha Basavapatna Subject: [PATCH for bnxt_re V3 11/21] bnxt_re: Support for AH verbs Date: Tue, 20 Dec 2016 01:13:21 -0800 Message-Id: <1482225211-22423-12-git-send-email-selvin.xavier@broadcom.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1482225211-22423-1-git-send-email-selvin.xavier@broadcom.com> References: <1482225211-22423-1-git-send-email-selvin.xavier@broadcom.com> Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch implements support for create_ah, destroy_ah, query_ah and modify_ah verbs. v3: Removes unwanted macros and does cleanup listed by checkpatch Signed-off-by: Eddie Wai Signed-off-by: Devesh Sharma Signed-off-by: Somnath Kotur Signed-off-by: Sriharsha Basavapatna Signed-off-by: Selvin Xavier --- drivers/infiniband/hw/bnxtre/bnxt_qplib_sp.c | 94 +++++++++++++++ drivers/infiniband/hw/bnxtre/bnxt_qplib_sp.h | 18 +++ drivers/infiniband/hw/bnxtre/bnxt_re_ib_verbs.c | 147 ++++++++++++++++++++++++ drivers/infiniband/hw/bnxtre/bnxt_re_ib_verbs.h | 11 ++ drivers/infiniband/hw/bnxtre/bnxt_re_main.c | 4 + include/uapi/rdma/bnxtre-abi.h | 7 ++ 6 files changed, 281 insertions(+) diff --git a/drivers/infiniband/hw/bnxtre/bnxt_qplib_sp.c b/drivers/infiniband/hw/bnxtre/bnxt_qplib_sp.c index 2bdfaf0..132dd29 100644 --- a/drivers/infiniband/hw/bnxtre/bnxt_qplib_sp.c +++ b/drivers/infiniband/hw/bnxtre/bnxt_qplib_sp.c @@ -416,3 +416,97 @@ int bnxt_qplib_add_pkey(struct bnxt_qplib_res *res, /* unlock */ return rc; } + +/* AH */ +int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct cmdq_create_ah req; + struct creq_create_ah_resp *resp; + u16 cmd_flags = 0; + u32 temp32[4]; + u16 temp16[3]; + + RCFW_CMD_PREP(req, CREATE_AH, cmd_flags); + + memcpy(temp32, ah->dgid.data, sizeof(struct bnxt_qplib_gid)); + req.dgid[0] = cpu_to_le32(temp32[0]); + req.dgid[1] = cpu_to_le32(temp32[1]); + req.dgid[2] = cpu_to_le32(temp32[2]); + req.dgid[3] = cpu_to_le32(temp32[3]); + + req.type = ah->nw_type; + req.hop_limit = ah->hop_limit; + req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[ah->sgid_index]); + req.dest_vlan_id_flow_label = cpu_to_le32((ah->flow_label & + CMDQ_CREATE_AH_FLOW_LABEL_MASK) | + CMDQ_CREATE_AH_DEST_VLAN_ID_MASK); + req.pd_id = cpu_to_le32(ah->pd->id); + req.traffic_class = ah->traffic_class; + + /* MAC in network format */ + memcpy(temp16, ah->dmac, 6); + req.dest_mac[0] = cpu_to_le16(temp16[0]); + req.dest_mac[1] = cpu_to_le16(temp16[1]); + req.dest_mac[2] = cpu_to_le16(temp16[2]); + + resp = (struct creq_create_ah_resp *) + bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, + NULL, 1); + if (!resp) { + dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH send failed"); + return -EINVAL; + } + if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) { + /* Cmd timed out */ + dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH timed out"); + return -ETIMEDOUT; + } + if (resp->status || + le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { + dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH failed "); + dev_err(&rcfw->pdev->dev, + "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", + resp->status, le16_to_cpu(req.cookie), + le16_to_cpu(resp->cookie)); + return -EINVAL; + } + ah->id = le32_to_cpu(resp->xid); + return 0; +} + +int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct cmdq_destroy_ah req; + struct creq_destroy_ah_resp *resp; + u16 cmd_flags = 0; + + /* Clean up the AH table in the device */ + RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags); + + req.ah_cid = cpu_to_le32(ah->id); + + resp = (struct creq_destroy_ah_resp *) + bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, + NULL, 1); + if (!resp) { + dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH send failed"); + return -EINVAL; + } + if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) { + /* Cmd timed out */ + dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH timed out"); + return -ETIMEDOUT; + } + if (resp->status || + le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { + dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH failed "); + dev_err(&rcfw->pdev->dev, + "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", + resp->status, le16_to_cpu(req.cookie), + le16_to_cpu(resp->cookie)); + return -EINVAL; + } + return 0; +} diff --git a/drivers/infiniband/hw/bnxtre/bnxt_qplib_sp.h b/drivers/infiniband/hw/bnxtre/bnxt_qplib_sp.h index 8e20924..26eac17 100644 --- a/drivers/infiniband/hw/bnxtre/bnxt_qplib_sp.h +++ b/drivers/infiniband/hw/bnxtre/bnxt_qplib_sp.h @@ -78,6 +78,22 @@ struct bnxt_qplib_gid { u8 data[16]; }; +struct bnxt_qplib_ah { + struct bnxt_qplib_gid dgid; + struct bnxt_qplib_pd *pd; + u32 id; + u8 sgid_index; + /* For Query AH if the hw table and SW table are differnt */ + u8 host_sgid_index; + u8 traffic_class; + u32 flow_label; + u8 hop_limit; + u8 sl; + u8 dmac[6]; + u16 vlan_id; + u8 nw_type; +}; + int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, struct bnxt_qplib_sgid_tbl *sgid_tbl, int index, struct bnxt_qplib_gid *gid); @@ -97,4 +113,6 @@ int bnxt_qplib_add_pkey(struct bnxt_qplib_res *res, bool update); int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, struct bnxt_qplib_dev_attr *attr); +int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah); +int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah); #endif /* __BNXT_QPLIB_SP_H__*/ diff --git a/drivers/infiniband/hw/bnxtre/bnxt_re_ib_verbs.c b/drivers/infiniband/hw/bnxtre/bnxt_re_ib_verbs.c index 0063258..c085dbd 100644 --- a/drivers/infiniband/hw/bnxtre/bnxt_re_ib_verbs.c +++ b/drivers/infiniband/hw/bnxtre/bnxt_re_ib_verbs.c @@ -492,6 +492,153 @@ struct ib_pd *bnxt_re_alloc_pd(struct ib_device *ibdev, return ERR_PTR(rc); } +/* Address Handles */ +int bnxt_re_destroy_ah(struct ib_ah *ib_ah) +{ + struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah); + struct bnxt_re_dev *rdev = ah->rdev; + int rc; + + rc = bnxt_qplib_destroy_ah(&rdev->qplib_res, &ah->qplib_ah); + if (rc) { + dev_err(rdev_to_dev(rdev), "Failed to destroy HW AH"); + return rc; + } + kfree(ah); + return 0; +} + +struct ib_ah *bnxt_re_create_ah(struct ib_pd *ib_pd, + struct ib_ah_attr *ah_attr) +{ + struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd); + struct bnxt_re_dev *rdev = pd->rdev; + struct bnxt_re_ah *ah; + int rc; + u16 vlan_tag; + u8 nw_type; + + struct ib_gid_attr sgid_attr; + + if (!(ah_attr->ah_flags & IB_AH_GRH)) { + dev_err(rdev_to_dev(rdev), "Failed to alloc AH: GRH not set"); + return ERR_PTR(-EINVAL); + } + ah = kzalloc(sizeof(*ah), GFP_ATOMIC); + if (!ah) + return ERR_PTR(-ENOMEM); + + ah->rdev = rdev; + ah->qplib_ah.pd = &pd->qplib_pd; + + /* Supply the configuration for the HW */ + memcpy(ah->qplib_ah.dgid.data, ah_attr->grh.dgid.raw, + sizeof(union ib_gid)); + /* + * If RoCE V2 is enabled, stack will have two entries for + * each GID entry. Avoiding this duplicte entry in HW. Dividing + * the GID index by 2 for RoCE V2 + */ + ah->qplib_ah.sgid_index = ah_attr->grh.sgid_index / 2; + ah->qplib_ah.host_sgid_index = ah_attr->grh.sgid_index; + ah->qplib_ah.traffic_class = ah_attr->grh.traffic_class; + ah->qplib_ah.flow_label = ah_attr->grh.flow_label; + ah->qplib_ah.hop_limit = ah_attr->grh.hop_limit; + ah->qplib_ah.sl = ah_attr->sl; + if (ib_pd->uobject && + !rdma_is_multicast_addr((struct in6_addr *) + ah_attr->grh.dgid.raw) && + !rdma_link_local_addr((struct in6_addr *) + ah_attr->grh.dgid.raw)) { + union ib_gid sgid; + + rc = ib_get_cached_gid(&rdev->ibdev, 1, + ah_attr->grh.sgid_index, &sgid, + &sgid_attr); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to query gid at index %d", + ah_attr->grh.sgid_index); + goto fail; + } + if (sgid_attr.ndev) { + if (is_vlan_dev(sgid_attr.ndev)) + vlan_tag = vlan_dev_vlan_id(sgid_attr.ndev); + dev_put(sgid_attr.ndev); + } + /* Get network header type for this GID */ + nw_type = ib_gid_to_network_type(sgid_attr.gid_type, &sgid); + switch (nw_type) { + case RDMA_NETWORK_IPV4: + ah->qplib_ah.nw_type = CMDQ_CREATE_AH_TYPE_V2IPV4; + break; + case RDMA_NETWORK_IPV6: + ah->qplib_ah.nw_type = CMDQ_CREATE_AH_TYPE_V2IPV6; + break; + default: + ah->qplib_ah.nw_type = CMDQ_CREATE_AH_TYPE_V1; + break; + } + rc = rdma_addr_find_l2_eth_by_grh(&sgid, &ah_attr->grh.dgid, + ah_attr->dmac, &vlan_tag, + &sgid_attr.ndev->ifindex, + NULL); + if (rc) { + dev_err(rdev_to_dev(rdev), "Failed to get dmac\n"); + goto fail; + } + } + + memcpy(ah->qplib_ah.dmac, ah_attr->dmac, ETH_ALEN); + rc = bnxt_qplib_create_ah(&rdev->qplib_res, &ah->qplib_ah); + if (rc) { + dev_err(rdev_to_dev(rdev), "Failed to allocate HW AH"); + goto fail; + } + + /* Write AVID to shared page. */ + if (ib_pd->uobject) { + struct ib_ucontext *ib_uctx = ib_pd->uobject->context; + struct bnxt_re_ucontext *uctx; + unsigned long flag; + u32 *wrptr; + + uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx); + spin_lock_irqsave(&uctx->sh_lock, flag); + wrptr = (u32 *)(uctx->shpg + BNXT_RE_AVID_OFFT); + *wrptr = ah->qplib_ah.id; + wmb(); /* make sure cache is updated. */ + spin_unlock_irqrestore(&uctx->sh_lock, flag); + } + + return &ah->ib_ah; + +fail: + kfree(ah); + return ERR_PTR(rc); +} + +int bnxt_re_modify_ah(struct ib_ah *ib_ah, struct ib_ah_attr *ah_attr) +{ + return 0; +} + +int bnxt_re_query_ah(struct ib_ah *ib_ah, struct ib_ah_attr *ah_attr) +{ + struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah); + + memcpy(ah_attr->grh.dgid.raw, ah->qplib_ah.dgid.data, + sizeof(union ib_gid)); + ah_attr->grh.sgid_index = ah->qplib_ah.host_sgid_index; + ah_attr->grh.traffic_class = ah->qplib_ah.traffic_class; + ah_attr->sl = ah->qplib_ah.sl; + memcpy(ah_attr->dmac, ah->qplib_ah.dmac, ETH_ALEN); + ah_attr->ah_flags = IB_AH_GRH; + ah_attr->port_num = 1; + ah_attr->static_rate = 0; + return 0; +} + /* Completion Queues */ int bnxt_re_destroy_cq(struct ib_cq *ib_cq) { diff --git a/drivers/infiniband/hw/bnxtre/bnxt_re_ib_verbs.h b/drivers/infiniband/hw/bnxtre/bnxt_re_ib_verbs.h index 1efb3c8..14c9e02 100644 --- a/drivers/infiniband/hw/bnxtre/bnxt_re_ib_verbs.h +++ b/drivers/infiniband/hw/bnxtre/bnxt_re_ib_verbs.h @@ -51,6 +51,12 @@ struct bnxt_re_pd { struct bnxt_qplib_dpi dpi; }; +struct bnxt_re_ah { + struct bnxt_re_dev *rdev; + struct ib_ah ib_ah; + struct bnxt_qplib_ah qplib_ah; +}; + struct bnxt_re_cq { struct bnxt_re_dev *rdev; spinlock_t cq_lock; /* protect cq */ @@ -102,6 +108,11 @@ struct ib_pd *bnxt_re_alloc_pd(struct ib_device *ibdev, struct ib_ucontext *context, struct ib_udata *udata); int bnxt_re_dealloc_pd(struct ib_pd *pd); +struct ib_ah *bnxt_re_create_ah(struct ib_pd *pd, + struct ib_ah_attr *ah_attr); +int bnxt_re_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr); +int bnxt_re_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr); +int bnxt_re_destroy_ah(struct ib_ah *ah); struct ib_cq *bnxt_re_create_cq(struct ib_device *ibdev, const struct ib_cq_init_attr *attr, struct ib_ucontext *context, diff --git a/drivers/infiniband/hw/bnxtre/bnxt_re_main.c b/drivers/infiniband/hw/bnxtre/bnxt_re_main.c index 0b2f669..f270b4c 100644 --- a/drivers/infiniband/hw/bnxtre/bnxt_re_main.c +++ b/drivers/infiniband/hw/bnxtre/bnxt_re_main.c @@ -452,6 +452,10 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev) ibdev->alloc_pd = bnxt_re_alloc_pd; ibdev->dealloc_pd = bnxt_re_dealloc_pd; + ibdev->create_ah = bnxt_re_create_ah; + ibdev->modify_ah = bnxt_re_modify_ah; + ibdev->query_ah = bnxt_re_query_ah; + ibdev->destroy_ah = bnxt_re_destroy_ah; ibdev->create_cq = bnxt_re_create_cq; ibdev->destroy_cq = bnxt_re_destroy_cq; ibdev->req_notify_cq = bnxt_re_req_notify_cq; diff --git a/include/uapi/rdma/bnxtre-abi.h b/include/uapi/rdma/bnxtre-abi.h index 5a6ff47..024579b 100644 --- a/include/uapi/rdma/bnxtre-abi.h +++ b/include/uapi/rdma/bnxtre-abi.h @@ -68,4 +68,11 @@ struct bnxt_re_cq_resp { __u32 rsvd; }; +enum bnxt_re_shpg_offt { + BNXT_RE_BEG_RESV_OFFT = 0x00, + BNXT_RE_AVID_OFFT = 0x10, + BNXT_RE_AVID_SIZE = 0x04, + BNXT_RE_END_RESV_OFFT = 0xFF0 +}; + #endif /* __BNXT_RE_UVERBS_ABI_H__*/