From patchwork Thu Nov 3 23:44:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adit Ranadive X-Patchwork-Id: 9411635 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 00BAE60585 for ; Thu, 3 Nov 2016 23:48:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E5C5A2AF77 for ; Thu, 3 Nov 2016 23:48:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DA5972AF86; Thu, 3 Nov 2016 23:48:48 +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 D37862AFC0 for ; Thu, 3 Nov 2016 23:48:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933372AbcKCXsq (ORCPT ); Thu, 3 Nov 2016 19:48:46 -0400 Received: from ex13-edg-ou-002.vmware.com ([208.91.0.190]:24608 "EHLO EX13-EDG-OU-002.vmware.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933240AbcKCXso (ORCPT ); Thu, 3 Nov 2016 19:48:44 -0400 Received: from sc9-mailhost1.vmware.com (10.113.161.71) by EX13-EDG-OU-002.vmware.com (10.113.208.156) with Microsoft SMTP Server id 15.0.1156.6; Thu, 3 Nov 2016 16:48:35 -0700 Received: from EX13-CAS-005.vmware.com (smtp-inbound.vmware.com [10.113.191.55]) by sc9-mailhost1.vmware.com (Postfix) with ESMTP id C29B2184B5; Thu, 3 Nov 2016 16:48:42 -0700 (PDT) Received: from EX13-MBX-036.vmware.com (10.113.191.77) by EX13-MBX-005.vmware.com (10.113.191.25) with Microsoft SMTP Server (TLS) id 15.0.1156.6; Thu, 3 Nov 2016 16:48:30 -0700 Received: from EX13-CAS-001.vmware.com (10.113.191.51) by EX13-MBX-036.vmware.com (10.113.191.77) with Microsoft SMTP Server (TLS) id 15.0.1156.6; Thu, 3 Nov 2016 16:48:29 -0700 Received: from NAM02-CY1-obe.outbound.protection.outlook.com (10.113.170.11) by EX13-CAS-001.vmware.com (10.113.191.51) with Microsoft SMTP Server (TLS) id 15.0.1156.6 via Frontend Transport; Thu, 3 Nov 2016 16:48:29 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=onevmw.onmicrosoft.com; s=selector1-vmware-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=nZnDDlLRwXFlAXrA6JZ6vEI0CsZEJ3r3CpeY7qPsjj4=; b=DxXgSf97/JDaOUSslx9+7siPqK0pGE1l2jbk8wvfnRmLunejzfrYwED5iu4+yqCx19VNy1jClVnm4nezB3QZtySmC2ixsoB659AOCsq5Bsy2iRL1ZZDXOW1sHfESQSTBJqkZc2b1Jvsf5XusTBPaySdrQCReTpq6Z/YOp58j184= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=aditr@vmware.com; Received: from gandalf.eng.vmware.com (208.91.1.34) by BLUPR0501MB836.namprd05.prod.outlook.com (10.141.251.150) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.707.1; Thu, 3 Nov 2016 23:48:23 +0000 From: Adit Ranadive To: , , CC: Adit Ranadive Subject: [PATCH 4/8] libpvrdma: Add queue pair functions Date: Thu, 3 Nov 2016 16:44:33 -0700 Message-ID: <1478216677-6150-5-git-send-email-aditr@vmware.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1478216677-6150-1-git-send-email-aditr@vmware.com> References: <1478216677-6150-1-git-send-email-aditr@vmware.com> MIME-Version: 1.0 X-Originating-IP: [208.91.1.34] X-ClientProxiedBy: BY2PR04CA052.namprd04.prod.outlook.com (10.141.249.170) To BLUPR0501MB836.namprd05.prod.outlook.com (10.141.251.150) X-MS-Office365-Filtering-Correlation-Id: 2ed1696d-da33-48f4-0c73-08d40443e676 X-Microsoft-Exchange-Diagnostics: 1; BLUPR0501MB836; 2:dsY5UBtWmkIhI5HEpXgiFCyq+dOv9B/YvETQPXu0XrFQZ3tZLizI5in7lcZhY60ZiqDj/WhBi6RGwbmc/QJOaAaua8w6TE0li6lg4apIO+1kn4nI791wZaXTKy+50qPzUJ6Uiqd4e1IVfkq1s3T9Wt4vckCucTULyUjOcWMy212b6LyHOVEYnkiAaG22Nn765Mcp+2NzW5SV4ucml6Kvfw==; 3:h4S+e3XCUQ8k8w4SuqGEr8f6i86fVLKv53ff50y94FMSRBNm/zcSRiJJUxDplOF+7D33nKkOZcE4wZ9LLzuGDzsdxErgC9apmb33buu3px+DbZ1WRCuynfy0O2Da5YCsfEpXEz6js263NzB2V7okRw== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BLUPR0501MB836; X-Microsoft-Exchange-Diagnostics: 1; BLUPR0501MB836; 25:otvaHJlZKz1fPE9CfuUASZ9gSybghRHtRHi3yvJ4VCDJ704zUEyCy7U/XolTX6OV1FCR5mCSi3DdaR9zsnnLM8NyzwzBrCrtJ+ErxBplN4Z+Cuz5TyQWB6VxC46C+n09zODerOyOIZ0QyLB7BODUu248Aqqf1hB3XwDEiJ0epXwIFMWEQP08qjghKmtoJSKHQ4+TAGvSLuhhsmMeq5dCAw5K/KzeU6GvzfeGJLu+a0KeWWkOeI76989u4l1K3J8m9hRHjCHjNe5ao9mhGcrwicvJ1wHxR4nhu4A2MWn75+Qn+uoLDXK8164jDHEYwYxYNZ6eQAj0yphUvmUbjUjK19bZV2SMWx5qnK07vpKk3bQjROjdlMJTCb1g4ZTNAHnSE5hNQXjlDTjvKFu1MVBYQwJgX3iIBb7QARRykYccJeK5PAiHhTkEmAG+a8tkF0aznBCCEGZlzd87zDOFob6wneRZsLha+xJhdjr8H6ErZOiL4iV/9AQDCRzqo3oiHA9TFoeP7UNw4sNiKMZGyN+P0Vsyem2ahloN/q5T9gYkl5cy3ZjZ9d97NzIGPlGBeeNNUoClzxvN1AiEGN945OfkDfi+1Lkw2TYnBgVBfxs3GzGzM/szrsh0cyyUdVO43pBX5j6diUL8ntK7QJthGiG3Y7ja7xBsF0VP2BwmA+yA/Ci7PhkJVkzRvD3PUal5WqMi+EUrt7z9jUGetKKMhlfDrMuM6ax76lUPa+5kPiwlmKQW6gokr2MlZSkEbTPEfr5IkCbVyu8hMU5Y5fCohiJc8VdbHHxAyRtTbqNAeVV8MxTagCveWprGg0HpKNFritPR X-LD-Processed: b39138ca-3cee-4b4a-a4d6-cd83d9dd62f0,ExtAddr X-Microsoft-Exchange-Diagnostics: 1; BLUPR0501MB836; 31:86XnqTnIrjWXuu2WPruZhAQTSJzbkkYvOHDQC7VnrnyRr5LdK5puUamO/66vAMCXCdOkroylyUyZMufOAczokKu2WThfo4PTabi/yf6bc17TQHK0RA/hTwnoiFfT9gGMO3+B3dKWs+2Nv+UQS2P0i9NMF9NenmTbk74++dDr5GObsTwueC7gIyek0Qymzp1p1xRTd9SppDL69/PxHkuMjRXL/TWFftOz5EGU4DgmxGm6MgL5Fp4zWgNA48oO6mAE; 20:qD1Q4o0uNhXgnHObvSTgHHTRY942VSRdrlbwTpmjjNIDOTqgWW5PzNLhWaCR3eB22jKO3mU15C8iF+R7JrA4kigyblOHGc1ZBwjci6/Pxt4pejN0e/g+cMI60HMgMnXy0I7PiPELuY5Ses6k4tZE2TQ5k6Vpd9E4f8vw2CWuVLI1zhg/ExRxoGPZ6gN74C6Oew5CBnXPn/GNH4Uq4MaEZyuC1p7gP1Oi/cmD1eFA5KYCcfKi/oWVjsSi/dLUyd0PBTzJmv5tTbObQWdbfMTWs22IDO32dn1JOYILDHNauiWZ2SDAoss52u6XpPPAj6rA05H96WI8SR073mO5R4/9Eu577DLUfUQmJkacaAmtbj9yEN50lwDJCUfP/HiKxUA4XKxUH9j70DrIIXMaiD90Bx7GJXJ1+f00vxPLK1HYLyq25/t/HNiIOv3H6roYKZxlrlgl6rrqwAV1aakZ/FOouiF5L4MfBCiU5VfGBqLtTm9VgOfC78TWnF9WINEhs5AF X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(250305191791016)(61668805478150)(22074186197030); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040176)(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046); SRVR:BLUPR0501MB836; BCL:0; PCL:0; RULEID:; SRVR:BLUPR0501MB836; X-Microsoft-Exchange-Diagnostics: 1; BLUPR0501MB836; 4:Nr2qsZnzrKlghOZ2tdUtz9KpA+kauk5Le7bA5ATU7ir25Yx+IW3TmHtCzaHdGvXNAG8SgUhLZ0AdjiqL3F+b7kpI2FduEC/ExEE6adsSPNCFiJgn8BHknZBFmWkYQljABdxnlA1NaYFVSifTns4buhsRkEj//lMfsCDT2h0hc2piO4y3/+00zVc12u1JsRqI9WF6hTgt2lGvSuQW/KmvlcY/VS3Q059imPb8EHIe3DwMXhuRXS/szOOiL+SXpv2OBiq4m+zp6kptKvSstsWD7m+pu66LpzUIAuplWlvhvpTfi1ajKiP9D1XjO/84uv4M0ZV5FKUqVKPlo66a9IFm9wmVpnMkVM9BPaJ6mtFn9tQMSI1VX7jl1zCFRLgURt6lKDZ5M3DqVVRCuCqCqrpR3GWzndxOn0pkksIzm5ptT1P+0E5qX9SlQggCSGjAosBR9P6Q1jsk2abtAZifqOlwwyvkIhow4bvw1UcPUmDvzx9u7P7b4QzSvxmk3Q7074l5NUSgDAw8A09T4WwtdqwD2w== X-Forefront-PRVS: 011579F31F X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6009001)(7916002)(199003)(189002)(15975445007)(8676002)(6116002)(5003940100001)(106356001)(5001770100001)(97736004)(3846002)(586003)(107886002)(19580395003)(19580405001)(81156014)(81166006)(189998001)(66066001)(47776003)(4001430100002)(50226002)(7846002)(92566002)(7736002)(305945005)(575784001)(2201001)(101416001)(6666003)(42186005)(50986999)(6636002)(86362001)(77096005)(6862003)(48376002)(50466002)(105586002)(76176999)(2950100002)(2906002)(4326007)(68736007)(36756003)(5660300001)(229853001)(33646002)(7099028)(2004002); DIR:OUT; SFP:1101; SCL:1; SRVR:BLUPR0501MB836; H:gandalf.eng.vmware.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (EX13-EDG-OU-002.vmware.com: aditr@vmware.com does not designate permitted sender hosts) Received-SPF: None (protection.outlook.com: vmware.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BLUPR0501MB836; 23:2LFzBtagdPd0MfKXexhZPGK3Qo2Uh+SouJOiRlQg?= =?us-ascii?Q?mwb73pxAsLHQ0v44SiVMx2OVHRqBoiWq9PcXQW7EP51Wpbzip0b5qBdcFD1d?= =?us-ascii?Q?bYESiVTuKvVr58JM2AyOYWZxtUNIVHSByLkVv3CuZkCXUBEuM7MpuC/Fk/3y?= =?us-ascii?Q?11S5ZyutxZwYLfFBAX125WVMtX5Tkk7FnBHkTG6f6iUABtO3F4elxVm/CvxN?= =?us-ascii?Q?n4IiBDXhWD9vAdqd73gIV7mbaweQ2SCcT+AONMinvKZv+cuZWTKBUyrMTuFF?= =?us-ascii?Q?YOzjPbJRftQxSgqfoSfRr0a/1ThiMywbrcekFYXhxuVb+9K545WoOswGYKC7?= =?us-ascii?Q?uLBM3IAlJU1J5hbYaXyUTfXR184T2ipg4xyfUPkO6zIGajlXHD97tWdExHEW?= =?us-ascii?Q?yXhrhPMZ4m80gV9ypOS6I+97hXHi+NBX9F9sKcYIH1ALjdeSwMWTlmkv9Tfj?= =?us-ascii?Q?Qo2/zkdnKu4a9L3zlvOEqTcS7qdrP4JXJcbiGd/MQ2TKEfKEqWlUn9CgYXm/?= =?us-ascii?Q?LwTfY8JoZCdC39XWW7ni5GhLy5NmhWHcjaFgJY9K70fIavWAQfS+1iUDwr9g?= =?us-ascii?Q?tXyApF/+xDnyCh20G3+sgZFyv8ktVbq3F6/NSd8HOORlPqVoSmm4O4yYTU26?= =?us-ascii?Q?PKgjGNB5qfVlBWkboVnywilwIqLz4FFMdzXYEHwz8MZmnWSsp7TPpylXs1iJ?= =?us-ascii?Q?5PtdkqhulQnxUjNzUkfVW0rXVoex+1/q2KoOm4vhj994Htq2G4sV/9YVN6cT?= =?us-ascii?Q?GIxNfUgTFrlMCFR4EIAR1vD8SO2o/7YlxtR5zSdmO7fk/udSdaaio7SxRvfh?= =?us-ascii?Q?aYoOroSKGGyr3elm7RlcxGpxxfaLzpQK3l01oRqLAZlEdlZ5vAVNcW3hbfEc?= =?us-ascii?Q?f1xJRpGzBoBfEpbOdu9tB6iEZFNJWAW4LXPGPJpf290s9x0SngyS0zRXvT5p?= =?us-ascii?Q?HrsFUWkubTdMXL6Nk+C7ey2P1rjr4cdKFLwOYRlEiAnfRzXweiNJfpwH4O5R?= =?us-ascii?Q?TOAZ0RDuPOkHg/e4xlDBGXiyxv2LB29dj4Z0b3j3rXBli5GOPcjEaaHgDeVM?= =?us-ascii?Q?kAOjyXaKUwrMiThWwLcvLT9XF/uY7dg4oQjolmTWEfQ4V3s5KOyq1813ejEA?= =?us-ascii?Q?6Zlj6enQq611XgqfIvxTbUag4/thN+jNCizGd3cB0UceoWZjm0NonTdwNVJT?= =?us-ascii?Q?hPW/WeKpmXV+NPbj0oeuSKFrXFse0wqgl35QuK/F6JuGEzKGp8GPBxm92NH1?= =?us-ascii?Q?VsV1gSRU+x1HOGpQQZU24YZYAkm8XABh2mmS5fU+?= X-Microsoft-Exchange-Diagnostics: 1; BLUPR0501MB836; 6:K2eRywz1PgQolIVF7lWum3x0Pdy/mlZjm3NcFdi11LODNHYyphdkZllLuvUl1K31yrlP6s0BtMwwLB2QKSL+ERjdMdAUDoCGLZymuc0b8P/oiybhk53/QeYXKK7ukIeMYxK9I7mCRq/QRZb5xvYAO5817PaGgwR0D0HQ9hRD90gkIWvPkBnzhzpW/ahUW765pGyPnSXKu+Wlouc1u+aT7ZqQOpjBfbV82W1LYSeb1znaXL8SudJOogMCmsGY3PDjuFFZQvTIXlabRGtPJrX4oh02RFaGcSfWxBJ9M3V9vKR2xWVpH1n1vVWJkwHDXV64; 5:P5t2eSt97yZtLZWov7R2I1PLM6ph2dkbPsrkdfjihE/x38YZJ7snWFzuSFwwU5Gfyf5odsc8j8HfrRZVz+tLf+rhQJui9ye4d7tLzvE2D7P2KYtYJBR5ke64EnHcHem8lhCl5Uq+PwGU9Nz1sUS/xyODv9nYit86Cxc1u7ccuFc=; 24:+xZcqf/dv2kuL3HrlGO6SP1ehYcH+DyBLBlfv2qzdHL3A+xLFRhODNzarW7kxP0zSa8Yb4FJxsbm6kzaiYRnwRVQ3Kf162YmZON3plKMe94= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BLUPR0501MB836; 7:rEQ+jsef4z+2cw3e4r5MmCkGxxYZK4jj/Gtfq74hwTMwKcNsvooj3A97W2weISQqz1q1GSvw54FeSc9CqYRq96GG1AhFgyVzJYuojlquY9XGy1seR3DRmI3x/4zLwgBdTETqV05E4vLhmwbcq8iRNueM2eivpLKAkcdP/B71l2bNsYeQO1wHLNDPC32b4i18xBoNoY8VyWcWg7cS/fAulfYNzaC1N2OF5y77fEIRijyXmJ9HTTWs77ta+6wGea7RlMbMwJe/fFlcji8i6wd3dPHcwdmTdv8X/2oHYWw5Iz5tEmLF0L3KcpDFV9wlpx+PzGcIrWV0gZEwUbc0UvAGEl/ieOkxbIZ7Vb5GMzHwMaE=; 20:1GJAzueEEXcYHvtmtoAIVrOOzFfLXKdmucKcZTjy9zerybi900gsDNYOqjzWfLjMYeK1Y+aQMW9x00DpzYFMRB2Otcxg3wZySeL/hklSFfs8tvTXwzh0di47b0hxPrwD0OlQuFJKsyqjw2ldfRj1V8CYe9kg/HbUVvG4z7UA2Fg= X-MS-Exchange-CrossTenant-OriginalArrivalTime: 03 Nov 2016 23:48:23.6043 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR0501MB836 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 Added functions to create, destroy, post on queue pairs. Signed-off-by: Adit Ranadive --- providers/pvrdma/qp.c | 505 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 505 insertions(+) create mode 100644 providers/pvrdma/qp.c diff --git a/providers/pvrdma/qp.c b/providers/pvrdma/qp.c new file mode 100644 index 0000000..46a0e32 --- /dev/null +++ b/providers/pvrdma/qp.c @@ -0,0 +1,505 @@ +/* + * Copyright (c) 2012-2016 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of EITHER the GNU General Public License + * version 2 as published by the Free Software Foundation or the BSD + * 2-Clause License. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License version 2 for more details at + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html. + * + * You should have received a copy of the GNU General Public License + * along with this program available in the file COPYING in the main + * directory of this source tree. + * + * The BSD 2-Clause License + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "pvrdma.h" + +int pvrdma_alloc_qp_buf(struct pvrdma_device *dev, struct ibv_qp_cap *cap, + enum ibv_qp_type type, struct pvrdma_qp *qp) +{ + qp->sq.wrid = malloc(qp->sq.wqe_cnt * sizeof(uint64_t)); + if (!qp->sq.wrid) + return -1; + + qp->rq.wrid = malloc(qp->rq.wqe_cnt * sizeof(uint64_t)); + if (!qp->rq.wrid) { + free(qp->sq.wrid); + return -1; + } + + /* Align page size for [rq][sq] */ + qp->rbuf.length = align(qp->rq.offset + + qp->rq.wqe_cnt * qp->rq.wqe_size, + dev->page_size); + qp->sbuf.length = align(qp->sq.offset + + qp->sq.wqe_cnt * qp->sq.wqe_size, + dev->page_size); + qp->buf_size = qp->rbuf.length + qp->sbuf.length; + + if (pvrdma_alloc_buf(&qp->rbuf, qp->rbuf.length, dev->page_size)) { + free(qp->sq.wrid); + free(qp->rq.wrid); + return -1; + } + + if (pvrdma_alloc_buf(&qp->sbuf, qp->sbuf.length, dev->page_size)) { + free(qp->sq.wrid); + free(qp->rq.wrid); + pvrdma_free_buf(&qp->rbuf); + return -1; + } + + memset(qp->rbuf.buf, 0, qp->rbuf.length); + memset(qp->sbuf.buf, 0, qp->sbuf.length); + + return 0; +} + +static void pvrdma_init_qp_queue(struct pvrdma_qp *qp) +{ + atomic_set(&(qp->sq.ring_state->cons_head), 0); + atomic_set(&(qp->sq.ring_state->prod_tail), 0); + atomic_set(&(qp->rq.ring_state->cons_head), 0); + atomic_set(&(qp->rq.ring_state->prod_tail), 0); +} + +struct ibv_qp *pvrdma_create_qp(struct ibv_pd *pd, + struct ibv_qp_init_attr *attr) +{ + struct pvrdma_device *dev = to_vdev(pd->context->device); + struct pvrdma_create_qp cmd; + struct ibv_create_qp_resp resp; + struct pvrdma_qp *qp; + int ret; + + attr->cap.max_recv_sge = + align_next_power2(max(1U, attr->cap.max_recv_sge)); + attr->cap.max_recv_wr = + align_next_power2(max(1U, attr->cap.max_recv_wr)); + attr->cap.max_send_sge = + align_next_power2(max(1U, attr->cap.max_send_sge)); + attr->cap.max_send_wr = + align_next_power2(max(1U, attr->cap.max_send_wr)); + + qp = calloc(1, sizeof(*qp)); + if (!qp) + return NULL; + + qp->rq.max_gs = attr->cap.max_recv_sge; + qp->rq.wqe_cnt = attr->cap.max_recv_wr; + qp->rq.offset = 0; + qp->rq.wqe_size = align_next_power2(sizeof(struct pvrdma_rq_wqe_hdr) + + sizeof(struct ibv_sge) * + qp->rq.max_gs); + + qp->sq.max_gs = attr->cap.max_send_sge; + qp->sq.wqe_cnt = attr->cap.max_send_wr; + /* Extra page for shared ring state */ + qp->sq.offset = dev->page_size; + qp->sq.wqe_size = align_next_power2(sizeof(struct pvrdma_sq_wqe_hdr) + + sizeof(struct ibv_sge) * + qp->sq.max_gs); + + /* Reset attr.cap, no srq for now */ + if (attr->srq) { + attr->cap.max_recv_wr = 0; + qp->rq.wqe_cnt = 0; + } + + /* Allocate [rq][sq] memory */ + if (pvrdma_alloc_qp_buf(dev, &attr->cap, attr->qp_type, qp)) + goto err; + + qp->sq.ring_state = qp->sbuf.buf; + qp->rq.ring_state = (struct pvrdma_ring *)&qp->sq.ring_state[1]; + pvrdma_init_qp_queue(qp); + + if (pthread_spin_init(&qp->sq.lock, PTHREAD_PROCESS_PRIVATE) || + pthread_spin_init(&qp->rq.lock, PTHREAD_PROCESS_PRIVATE)) + goto err_free; + + memset(&cmd, 0, sizeof(cmd)); + cmd.rbuf_addr = (uintptr_t)qp->rbuf.buf; + cmd.rbuf_size = qp->rbuf.length; + cmd.sbuf_addr = (uintptr_t)qp->sbuf.buf; + cmd.sbuf_size = qp->sbuf.length; + cmd.qp_addr = (uintptr_t) qp; + + ret = ibv_cmd_create_qp(pd, &qp->ibv_qp, attr, + &cmd.ibv_cmd, sizeof(cmd), + &resp, sizeof(resp)); + + if (ret) + goto err_free; + + to_vctx(pd->context)->qp_tbl[qp->ibv_qp.qp_num & 0xFFFF] = qp; + + /* If set, each WR submitted to the SQ generate a completion entry */ + if (attr->sq_sig_all) + qp->sq_signal_bits = htonl(PVRDMA_WQE_CTRL_CQ_UPDATE); + else + qp->sq_signal_bits = 0; + + return &qp->ibv_qp; + +err_free: + if (qp->sq.wqe_cnt) + free(qp->sq.wrid); + if (qp->rq.wqe_cnt) + free(qp->rq.wrid); + pvrdma_free_buf(&qp->rbuf); + pvrdma_free_buf(&qp->sbuf); +err: + free(qp); + + return NULL; +} + +int pvrdma_query_qp(struct ibv_qp *ibqp, struct ibv_qp_attr *attr, + int attr_mask, + struct ibv_qp_init_attr *init_attr) +{ + struct ibv_query_qp cmd; + struct pvrdma_qp *qp = to_vqp(ibqp); + int ret; + + ret = ibv_cmd_query_qp(ibqp, attr, attr_mask, init_attr, + &cmd, sizeof(cmd)); + if (ret) + return ret; + + /* Passing back */ + init_attr->cap.max_send_wr = qp->sq.wqe_cnt; + init_attr->cap.max_send_sge = qp->sq.max_gs; + init_attr->cap.max_inline_data = qp->max_inline_data; + + attr->cap = init_attr->cap; + + return 0; +} + +int pvrdma_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr, + int attr_mask) +{ + struct ibv_modify_qp cmd; + int ret; + + /* Sanity check */ + if (!attr_mask) + return 0; + + ret = ibv_cmd_modify_qp(qp, attr, attr_mask, &cmd, sizeof(cmd)); + + if (!ret && + (attr_mask & IBV_QP_STATE) && + attr->qp_state == IBV_QPS_RESET) { + pvrdma_cq_clean(to_vcq(qp->recv_cq), qp->qp_num); + if (qp->send_cq != qp->recv_cq) + pvrdma_cq_clean(to_vcq(qp->send_cq), qp->qp_num); + pvrdma_init_qp_queue(to_vqp(qp)); + } + + return ret; +} + +static void pvrdma_lock_cqs(struct ibv_qp *qp) +{ + struct pvrdma_cq *send_cq = to_vcq(qp->send_cq); + struct pvrdma_cq *recv_cq = to_vcq(qp->recv_cq); + + if (send_cq == recv_cq) + pthread_spin_lock(&send_cq->lock); + else if (send_cq->cqn < recv_cq->cqn) { + pthread_spin_lock(&send_cq->lock); + pthread_spin_lock(&recv_cq->lock); + } else { + pthread_spin_lock(&recv_cq->lock); + pthread_spin_lock(&send_cq->lock); + } +} + +static void pvrdma_unlock_cqs(struct ibv_qp *qp) +{ + struct pvrdma_cq *send_cq = to_vcq(qp->send_cq); + struct pvrdma_cq *recv_cq = to_vcq(qp->recv_cq); + + if (send_cq == recv_cq) + pthread_spin_unlock(&send_cq->lock); + else if (send_cq->cqn < recv_cq->cqn) { + pthread_spin_unlock(&recv_cq->lock); + pthread_spin_unlock(&send_cq->lock); + } else { + pthread_spin_unlock(&send_cq->lock); + pthread_spin_unlock(&recv_cq->lock); + } +} + +int pvrdma_destroy_qp(struct ibv_qp *ibqp) +{ + struct pvrdma_context *ctx = to_vctx(ibqp->context); + struct pvrdma_qp *qp = to_vqp(ibqp); + int ret; + + ret = ibv_cmd_destroy_qp(ibqp); + if (ret) { + return ret; + } + + pvrdma_lock_cqs(ibqp); + /* Dump cqs */ + __pvrdma_cq_clean(to_vcq(ibqp->recv_cq), ibqp->qp_num); + + if (ibqp->send_cq != ibqp->recv_cq) + __pvrdma_cq_clean(to_vcq(ibqp->send_cq), ibqp->qp_num); + pvrdma_unlock_cqs(ibqp); + + free(qp->sq.wrid); + free(qp->rq.wrid); + pvrdma_free_buf(&qp->rbuf); + pvrdma_free_buf(&qp->sbuf); + ctx->qp_tbl[ibqp->qp_num & 0xFFFF] = NULL; + free(qp); + + return 0; +} + +static void *get_rq_wqe(struct pvrdma_qp *qp, int n) +{ + return qp->rbuf.buf + qp->rq.offset + (n * qp->rq.wqe_size); +} + +static void *get_sq_wqe(struct pvrdma_qp *qp, int n) +{ + return qp->sbuf.buf + qp->sq.offset + (n * qp->sq.wqe_size); +} + +int pvrdma_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr, + struct ibv_send_wr **bad_wr) +{ + struct pvrdma_context *ctx = to_vctx(ibqp->context); + struct pvrdma_qp *qp = to_vqp(ibqp); + int ind; + int nreq = 0; + struct pvrdma_sq_wqe_hdr *wqe_hdr; + struct ibv_sge *sge; + int ret = 0; + int i; + + /* + * In states lower than RTS, we can fail immediately. In other states, + * just post and let the device figure it out. + */ + if (ibqp->state < IBV_QPS_RTS) { + *bad_wr = wr; + return EINVAL; + } + + pthread_spin_lock(&qp->sq.lock); + ind = pvrdma_idx(&(qp->sq.ring_state->prod_tail), qp->sq.wqe_cnt); + if (ind < 0) { + pthread_spin_unlock(&qp->sq.lock); + ret = EINVAL; + goto out; + } + + for (nreq = 0; wr; ++nreq, wr = wr->next) { + unsigned int tail; + + if (pvrdma_idx_ring_has_space(qp->sq.ring_state, + qp->sq.wqe_cnt, &tail) <= 0) { + ret = ENOMEM; + *bad_wr = wr; + goto out; + } + + if (wr->num_sge > qp->sq.max_gs) { + ret = EINVAL; + *bad_wr = wr; + goto out; + } + + wqe_hdr = (struct pvrdma_sq_wqe_hdr *)get_sq_wqe(qp, ind); + wqe_hdr->wr_id = wr->wr_id; + wqe_hdr->num_sge = wr->num_sge; + wqe_hdr->opcode = ibv_wr_opcode_to_pvrdma(wr->opcode); + wqe_hdr->send_flags = ibv_send_flags_to_pvrdma(wr->send_flags); + if (wr->opcode == IBV_WR_SEND_WITH_IMM || + wr->opcode == IBV_WR_RDMA_WRITE_WITH_IMM) + wqe_hdr->ex.imm_data = wr->imm_data; + + switch (ibqp->qp_type) { + case IBV_QPT_UD: + wqe_hdr->wr.ud.remote_qpn = wr->wr.ud.remote_qpn; + wqe_hdr->wr.ud.remote_qkey = wr->wr.ud.remote_qkey; + wqe_hdr->wr.ud.av = to_vah(wr->wr.ud.ah)->av; + break; + case IBV_QPT_RC: + switch (wr->opcode) { + case IBV_WR_RDMA_READ: + case IBV_WR_RDMA_WRITE: + case IBV_WR_RDMA_WRITE_WITH_IMM: + wqe_hdr->wr.rdma.remote_addr = + wr->wr.rdma.remote_addr; + wqe_hdr->wr.rdma.rkey = wr->wr.rdma.rkey; + break; + case IBV_WR_ATOMIC_CMP_AND_SWP: + case IBV_WR_ATOMIC_FETCH_AND_ADD: + wqe_hdr->wr.atomic.remote_addr = wr->wr.atomic.remote_addr; + wqe_hdr->wr.atomic.rkey = wr->wr.atomic.rkey; + wqe_hdr->wr.atomic.compare_add = wr->wr.atomic.compare_add; + if (wr->opcode == IBV_WR_ATOMIC_CMP_AND_SWP) + wqe_hdr->wr.atomic.swap = wr->wr.atomic.swap; + break; + default: + /* No extra segments required for sends */ + break; + } + break; + default: + fprintf(stderr, PFX "invalid post send opcode\n"); + ret = EINVAL; + *bad_wr = wr; + goto out; + } + + /* Write each segment */ + sge = (struct ibv_sge *)&wqe_hdr[1]; + for (i = 0; i < wr->num_sge; i++) { + sge->addr = wr->sg_list[i].addr; + sge->length = wr->sg_list[i].length; + sge->lkey = wr->sg_list[i].lkey; + sge++; + } + + pvrdma_idx_ring_inc(&(qp->sq.ring_state->prod_tail), + qp->sq.wqe_cnt); + + wmb(); + + qp->sq.wrid[ind] = wr->wr_id; + ++ind; + if (ind >= qp->sq.wqe_cnt) + ind = 0; + } + +out: + if (nreq) + pvrdma_write_uar_qp(ctx->uar, + PVRDMA_UAR_QP_SEND | ibqp->qp_num); + + wmb(); + pthread_spin_unlock(&qp->sq.lock); + + return ret; +} + +int pvrdma_post_recv(struct ibv_qp *ibqp, struct ibv_recv_wr *wr, + struct ibv_recv_wr **bad_wr) +{ + struct pvrdma_context *ctx = to_vctx(ibqp->context); + struct pvrdma_qp *qp = to_vqp(ibqp); + struct pvrdma_rq_wqe_hdr *wqe_hdr; + struct ibv_sge *sge; + int nreq; + int ind; + int i; + int ret = 0; + + if (!wr || !bad_wr) + return EINVAL; + + /* + * In the RESET state, we can fail immediately. For other states, + * just post and let the device figure it out. + */ + if (ibqp->state == IBV_QPS_RESET) { + *bad_wr = wr; + return EINVAL; + } + + pthread_spin_lock(&qp->rq.lock); + + ind = pvrdma_idx(&(qp->rq.ring_state->prod_tail), qp->rq.wqe_cnt); + if (ind < 0) { + pthread_spin_unlock(&qp->rq.lock); + *bad_wr = wr; + return EINVAL; + } + + for (nreq = 0; wr; ++nreq, wr = wr->next) { + unsigned int tail; + + if (pvrdma_idx_ring_has_space(qp->rq.ring_state, + qp->rq.wqe_cnt, &tail) <= 0) { + ret = ENOMEM; + *bad_wr = wr; + goto out; + } + + if (wr->num_sge > qp->rq.max_gs) { + ret = EINVAL; + *bad_wr = wr; + goto out; + } + + /* Fetch wqe */ + wqe_hdr = (struct pvrdma_rq_wqe_hdr *)get_rq_wqe(qp, ind); + wqe_hdr->wr_id = wr->wr_id; + wqe_hdr->num_sge = wr->num_sge; + + sge = (struct ibv_sge *)(wqe_hdr + 1); + for (i = 0; i < wr->num_sge; ++i) { + sge->addr = (uint64_t)wr->sg_list[i].addr; + sge->length = wr->sg_list[i].length; + sge->lkey = wr->sg_list[i].lkey; + sge++; + } + + pvrdma_idx_ring_inc(&qp->rq.ring_state->prod_tail, + qp->rq.wqe_cnt); + + qp->rq.wrid[ind] = wr->wr_id; + ind = (ind + 1) & (qp->rq.wqe_cnt - 1); + } + +out: + if (nreq) + pvrdma_write_uar_qp(ctx->uar, + PVRDMA_UAR_QP_RECV | ibqp->qp_num); + + pthread_spin_unlock(&qp->rq.lock); + return ret; +}