From patchwork Mon Jun 26 18:07:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Kalderon, Michal" X-Patchwork-Id: 9810271 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 A894660329 for ; Mon, 26 Jun 2017 18:15:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A6320285DA for ; Mon, 26 Jun 2017 18:15:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 98F8E285ED; Mon, 26 Jun 2017 18:15:58 +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 1C0AC285DA for ; Mon, 26 Jun 2017 18:15:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751403AbdFZSPz (ORCPT ); Mon, 26 Jun 2017 14:15:55 -0400 Received: from mail-bl2nam02on0053.outbound.protection.outlook.com ([104.47.38.53]:39652 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751386AbdFZSPx (ORCPT ); Mon, 26 Jun 2017 14:15:53 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=CAVIUMNETWORKS.onmicrosoft.com; s=selector1-cavium-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=hKr26DTKod1kMK2QOFSRTHUzlKYasAEC1pUNRdyhTfY=; b=h12rSK1fgSLlzAC0BrIhUtKNYZ0OTdVCo7s8r8i4EuknkKKRiBGk2WeWWJECwdzZJ1sGNO1B5T2f7AI9sAtQP7CI1FPG4b4BNNGt3vdPngcrrGnahsOa8lGYy+pLEjD/bZ0rlz826cUbfchacH66xC20zSTX+rz68e1SYdIQSDI= Received: from SN1PR0701CA0051.namprd07.prod.outlook.com (10.163.126.19) by SN2PR0701MB1023.namprd07.prod.outlook.com (10.160.57.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1178.14; Mon, 26 Jun 2017 18:15:50 +0000 Received: from BY2FFO11FD029.protection.gbl (2a01:111:f400:7c0c::126) by SN1PR0701CA0051.outlook.office365.com (2a01:111:e400:52fd::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1199.15 via Frontend Transport; Mon, 26 Jun 2017 18:15:50 +0000 Authentication-Results: spf=none (sender IP is 50.232.66.26) smtp.mailfrom=cavium.com; vger.kernel.org; dkim=none (message not signed) header.d=none; vger.kernel.org; dmarc=none action=none header.from=cavium.com; Received-SPF: None (protection.outlook.com: cavium.com does not designate permitted sender hosts) Received: from CAEXCH02.caveonetworks.com (50.232.66.26) by BY2FFO11FD029.mail.protection.outlook.com (10.1.14.212) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.1199.9 via Frontend Transport; Mon, 26 Jun 2017 18:15:50 +0000 Received: from lb-tlvb-michal.il.qlogic.com.com (10.185.6.89) by CAEXCH02.caveonetworks.com (10.17.4.29) with Microsoft SMTP Server id 14.2.347.0; Mon, 26 Jun 2017 11:15:48 -0700 From: Michal Kalderon To: , , , , , , , CC: Michal Kalderon , Ram Amrani , Ariel Elior Subject: [RFC 18/19] RDMA/qedr: Add iWARP connection management functions Date: Mon, 26 Jun 2017 21:07:08 +0300 Message-ID: <1498500429-22557-19-git-send-email-Michal.Kalderon@cavium.com> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1498500429-22557-1-git-send-email-Michal.Kalderon@cavium.com> References: <1498500429-22557-1-git-send-email-Michal.Kalderon@cavium.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:50.232.66.26; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(39850400002)(39840400002)(39410400002)(39450400003)(39400400002)(2980300002)(428002)(45914002)(199003)(189002)(9170700003)(105586002)(77096006)(36756003)(2906002)(107886003)(5003940100001)(54906002)(2950100002)(2201001)(38730400002)(189998001)(86362001)(6666003)(5660300001)(101416001)(8936002)(50226002)(81166006)(356003)(4326008)(76176999)(50986999)(47776003)(48376002)(50466002)(478600001)(72206003)(104016004)(106466001)(8676002)(305945005); DIR:OUT; SFP:1101; SCL:1; SRVR:SN2PR0701MB1023; H:CAEXCH02.caveonetworks.com; FPR:; SPF:None; MLV:sfv; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD029; 1:oX3Nz3KFTAeDATQRhj/+BH49Io83GNmx+soiySHmNgF0Ooj00x0CXwxLLtDdczngQ4ZtGobeCQddEgrmE/s8X2nbuE8urfXomZb/WHW9x3jzTPiUiY0+Q138SHE7//NFVbhKwMlw8z8lZSlzt90OTF332Vf+GC8nU8D+FyQlelok6SBgrZaQACUmAEAKqk4x+cABaOOcYx8PbgH6V9BzCKUr+PHG8Kf0nkl46ems458mtVEsPdjKvr/gb5SMi1CSIpny9FfemIPIiNlOsXVov8Hras1St4LCkPIsEq18dkcMMEDxh4KAMH8Yg2gIeYVS2SWOdAqKzK9xW4QwbUKRuqek8U/Bkg9In/6ey+OiOQF/eVWtJJ7bX315A7PXuchBo5+qNE061RAh7h8EByCAXK4v4pdqcH5Hh4iFl3APryysREy5EDxT1fEh2J9qgQXqDgyrtG11AqhFXEzpVWrfPHVTMQWvTHE/iAaKcd4u9uU1/5wjrnt9yIcjgwkpq5BAg4OSD1tne92qafqa7y0gh/XBer554yngsKN0YkkABWGuM/y4Qmu2U92m29S8DATZlypzdgidmhb986Nf9iNXvWm01uXXXWnGTbAiq6xAW/gNNZKvB9YJ0OCOrLlpa1z+T+K6/QVQa6BMwcO6cEumYm3RzzJ+QmHslIuwVVmbLT6v/JJoeq2K7V65JKrXDrXJNA2iCN5nJb63Cz9nB6sCJ8PHWINoBFGr5fI0TiEmBcnl1Y1Cl4J3dZ2aCxxu84zlCmYWUNojXckI8C2uO/uW6zGQ+hBLjiVFFNdZITpH4AkRS0LiA1OL4gavTkFTKIrWTqqVnfjU972VxHxj3HNJTDLU/htdjnYcPPqhT1hmFM8= X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: c04a1fa3-d77b-41f6-f52d-08d4bcbf601a X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(300000500095)(300135000095)(300000501095)(300135300095)(22001)(300000502095)(300135100095)(2017030254075)(300000503095)(300135400095)(201703131423075)(201703031133081)(300000504095)(300135200095)(300000505095)(300135600095)(300000506067)(300135500095); SRVR:SN2PR0701MB1023; X-Microsoft-Exchange-Diagnostics: 1; SN2PR0701MB1023; 3:TCkWHOeahlg/IGJ7iuKO+kwQq8tB0G38Qp6/Hy64dlqx0xATIDjo6LfpCQJdPeDuORfg35zxI9dpnjxnYuTSbFuKQubdrND2C1kflD5jD0U+FvjZ9MXmwoFFIz4144eSu7RqB57JLL0PJeLODcSP6VJrAUKf6U1AV72h5NhBuNMfBgzIG7BhMB4duPdXMSUJ+zJA4Jp0p9vWqtKaM7rVfPixtgIBtxphwI7VCftIPiI8ayKrQ9cZzBlTyMwiMoY1wTEjMU2yhp2DPhHLnpAzXWYThRyOCyx9GzxdiG5UCY6/QYShcmTy6j8OBumlQBqY68RRIjIeBo8puuqSQggNav2casEGAj5VCsXXeqZddCCXvAGjAZfP71AX9DJd0GEqXNB6r/9ayPB1dtfAq8yMakW61m3LoTm3tqKpt9oSme6HKDPMAR1NYPrM25bVI9NbwgivjWwujVWyrqX223p2me/D/LJ3wjIY/+F6iFhwV4GW4budKXh05SJmN1zNBfZ8PyRc+PXkY9mZx1eQjzKHO6xjdvkN4HvITu5/WHiswyUT3IotyuTK4huN38PjxfWzCnfW313P+3XBS3E/0IPvztjPkUEtdYRDLybiM8ky04wPfEI9uDRoPY6XMtykac0l46zf72k9TCY/K8/6FnIqlyj7SbEHVfSHFo8vwizjPfZkCSnI/8vbIjXwQ3w9rvCSZUJG3oj/0d9fLTnKDFLEkRhLyIFO9EGKBIFhW46EHMF9+wHf19tNyajw1UaUfT0xxNDf2UdjBugH74M+usTObUTjGeq2Q1Ok/WpdmsZT506fwbpKx216B2oMP6M5iiXZYUTS3Fte58+Gi0GmOYuMn+3eqYKyUu9XSQOUG1PHwfOy6HdxiIz3CBA/HvI9hdzx X-MS-TrafficTypeDiagnostic: SN2PR0701MB1023: X-Microsoft-Exchange-Diagnostics: 1; SN2PR0701MB1023; 25:oCGMPQ6kSrBxuVRgyKkCqrwHOCBwIBD7oVW3azbfwzooGIkmtm8bBTgpk5341pJtjjs1i781jjpe7ofaMaXHsYp4ZE+i8Z//HLgtm1mZhvPfGo4LcogimHgCL889AzkxO302qC6PH+rS252EQhyWcR/5g0fjI3H69ve+i+6K7fCbDxsziGnsGaz7U3r912s84JSdUlUdZI7NDixbPhdYhlbWNWNqM1mpylCXV5FfjlSK4EKjlzDXU7sZqAZ8dlBlIe2nCvQL7rlmnjXHXNcxtRtQ4tGgQujgx4Il0FVTEthWbaJlLJQsBqVbou4+gEVATuFV5MM+izYp8pmQ7BbHEqwlWZVd6k12NOQxS2+Kvm2cLQ61hRj4+wA0vNzo4iKfSaJtmVKrd5aSzJ7t6dkcJHOBJxTXLaaHOmhhAPwQ37ps+kO49MC2yNBz/99OhjT5pnLmuyswRCz76fzeXBeIwuK2FyCM7C/iOfksZFioiI0bu5tHrxiL5jGQz1DDxdawgT5Sxbr0a7CGm0pcYO2A9VAmFFqwcYN5Mw0bKVPrPNcqvAK4Ih9oReDi+sl2I4QuJvHBcctRRCoO36hUe9d5Jk2swcRSTHgagPjgbY7hWAJzgPDjs6i4uMPxtJ978ELZ/Efrk/vQiOQ/qloZiiQpoINKUHErXlXMB2Rhfy+2YZOSjjHfWl2df6otnjB64rXyeb0PcKuzu11KjNeNEiH5YMnkRz4KJyXxCacX+cS8L2Oqm9mAANGV6Sk8l26kfW7tDsoQFig5iSb5f1z4mAZlZ3W3e/t5AyObbAZ8jK1Z6EMJibM5VWlejyZq99Y8ztSh8qkhTkB6K/iMJ70+6cYE6wp/P3INIEzvmIIlfgoyT9YV0SvXtiu3QvKLjqNsUL28fGA9CLSOUfqoCPGYIYrMhhvOgfYVdZlOcdGBGqq cCEQ= X-Microsoft-Exchange-Diagnostics: 1; SN2PR0701MB1023; 31:/f6Ylx2mTS8ARvLHW1I4UCHyb1Zb5TABWHtzkxZWlzufPGHOlCgLeqVhMIi4T5sCERQGPAEYsHncuafQZVJwN8IApFdxqaGECieUYZQlIR6796LHwhVMsKvkmCgFc4Yi56sYDC2llBuEqNMPk/HOZVMCLvNFZRXJGwz855iMiBhzI4IbU2j1fnjynHg6BIa7TeKGySZL25n15xH8MW0QjbyCWpK6/Php98iABrHQDkwHxw8ZX0o9vSsskFHYp0OQWxjZ0YUHCueASrg3IlwsgCeBZiu1ggbVzdjn0SfCpm/8FzReFEfaXx3UbTH25+ibrLuywOkeqLLvizny8uYxiQKWlnlwmC5WoXg8fbgpTcRQfAZHDb0nGIqkKo/oALhv/rfnBKwH8VSH7oao588Y0wDOcC6udsk9MrzKpVjigpZ5VjxhE80P81IMEQuNSaNfcNNgfEb/VvWC1l+fWKLmlFrdfkS4DFHbLwfVvYW5ffs3HZEA1OAxJ0eqDYtYAo7nvuD1ysWajnf+jU9iKR/ysC+91pkni7mTxdL9EvKchAmkr2rsl9hl1OB6HHZC2mk4ooVYWCy14yHigslZL6T+fynGl+lEhcjQaV/phjVNwg9WJw3+Z9L0JstQwHDMMa0N+OkB+2MmJ6BBPYrhGBpSd5vNH9YTy1aiRGB4/bZWd2KeQdiISutaw5MvjjlcubPk1HoKY//78zzbrrqeQymWEA== X-Microsoft-Exchange-Diagnostics: 1; SN2PR0701MB1023; 20:ZwjJPFWDdtZuJ2PJZYPS5BPmNQKHGeH24RqQhHz7GYb17vWFzGoynjeQoFlsv4EarBYoc2Hl19HUXwyVaStdVpFtF0WFapprfMg0obws4gpYWHRFhm9nTQA18y49onhLVmizgb5wTM3NRTyRCk+Ppp3BTWNc4lq1z2NKHTYewaC2pbbMfyOA5TCH6QoRMpNOh/n5xncCZPBlO7/3/sapwALlJtpIUG4NaJyqIkV322VuxRg/TmWMcXQXvA49iCk5ISq+YieJ/MMorPEcH90rADGSGe9sgLQfHZ/HQyFI31uQG1QYGX+wEQOAVKNWryf1KQ0qCHn2WH+7l0rglN/lRxJbtRFK3tLubc6aqK8H4fQf3SH+nNQq2+RRczNCs0doObE6QXkm854x6DCl5iy5vrYt8zNKfTUCbq3uLyrQy9TrxHJmVmXajFxz+o6pqmvJq2HoaZxwJKMXQeGw2X9NnQITo2x2ulQKzwlqvqevYhgEtiNPOCIniKF9Hp4zS4X9 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(236129657087228)(148574349560750)(21532816269658); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(601004)(2401047)(13018025)(13016025)(8121501046)(5005006)(100000703101)(100105400095)(10201501046)(93006095)(93001095)(3002001)(6041248)(20161123558100)(20161123560025)(20161123562025)(20161123564025)(20161123555025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(6072148)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:SN2PR0701MB1023; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:SN2PR0701MB1023; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; SN2PR0701MB1023; 4:RSsCtGPTJ8d1UFv0sOfOtfYdmMRXznu9+m5gup/g?= =?us-ascii?Q?G2+QYBEl2E4uDnoDy8FfDKw79neu4rjtleCAfNvZJx8LaplNsGZD5HjWqcWl?= =?us-ascii?Q?MdoARjk19OgN6o4S9Y325fmfSMsAu/zwv7NzCasFSsZTzUolCaNHXB0na2Yn?= =?us-ascii?Q?P/Wzep+FIcZfUfHBs+CZKSD0y4T/eeLyPVBkIHFoxDGpNHPg/Ufv5pC1S7Um?= =?us-ascii?Q?r3NWRMY3dFblrqbqWf7K/9ADbaaeVO3pLfAK12yLvergZoYA//6GprsYhioa?= =?us-ascii?Q?zV2aoqFIaDlXQG7/JPYyVJ8sBoQFtWM4IBr0WF5OMvbY+pQ2ovgmVuaBHx1c?= =?us-ascii?Q?G4bO5cBgQjEF8xYWHSWb1LYKt4Al35jlDORFWP6+ECe3djwpxL/vmV2kIETH?= =?us-ascii?Q?n6zeLmKxnoerCgeDi1VCUlOR5fWN53An4unTQM2nr5TmKcPvt2zrsn61IZKi?= =?us-ascii?Q?n4WaYyzY4tnGMIAjAA/Qv0gh7pnTEKxu57RIVo5KpxPbufSGWfPrXIYnxUdo?= =?us-ascii?Q?f0maDqVcqx798uLhmPLZSlRUU4+AwlEA9vGA3/oiPYORtLWmgpD7f052+YWo?= =?us-ascii?Q?wJg1QDrMvL/5nkRCRgYqnUW0IElaW4KSf/RkmsI2evzjqW5QnsuhH2HhHqLv?= =?us-ascii?Q?8tDMtd32vUjNumpWG7WS0M0e0hmhzSsD4qevVJMIN5erLPItO7MVQkDdYO/x?= =?us-ascii?Q?ajXdt1euJ/QdgYib9yY0WkAw73AS2VQK5PgyC0PaPJBs+7YhXJjgN8HDJcLL?= =?us-ascii?Q?+3Y+PLTuR+mor//Gnz5oMzVzOnz4IBk43pv9/xDRSknW+b885YSlWiWcSZrp?= =?us-ascii?Q?HAm+uwcsLKI9a6kHwFGOxQfkU2dM2jRKEUFx8ELZtYKLBY52lXXigyQGs/CA?= =?us-ascii?Q?InuilOdluNPyJWKcJ5YmAtK1ftUnrTvXBkw3Ibgyl35Ly7/lXlHhJOyk0Adj?= =?us-ascii?Q?03C06YjbSnibCik8lcN4xT2Zv1nl/qwU+uor53JUpVtG1Jf2DDUAPyDddxDy?= =?us-ascii?Q?I8NKsqLDHR6up+sMFE1auzeKxLqIGUww+SiCofVU8rkRBv1r7ngmNQNQjG2Q?= =?us-ascii?Q?xTD+RYDpxdnPGT+JBcwl92n8/a7SSi/LfcKWS06VwH5mNjfZ0JSU+vS+uZLy?= =?us-ascii?Q?Rnhggi81WhssaXLekENEBfzQ7QgUOyfjM6aWzpHYeVpFxnypWCQWt0KBZ88U?= =?us-ascii?Q?fSe1ExJtIB1ZhIOoNCN+bNYfsIAf+PHJB8PyxpCibvLQ4MFJ/ghZtXhu1Vvd?= =?us-ascii?Q?MCq0dNdt2P+XyHUCF9DblKdVlMz/00Q/rtRJWY7VGITi7Ppd4J2ldFk0NWD9?= =?us-ascii?Q?wQ=3D=3D?= X-Forefront-PRVS: 0350D7A55D X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; SN2PR0701MB1023; 23:8jXdnx6cvPeFEBYG5ToC/QUuWNmcUKFtD6CAq8c?= =?us-ascii?Q?lH5bh6hUwAW0K2ohah52DFENkHuVpgue3UJ7VcTJWSOd4K1MQal/AwjhdFbK?= =?us-ascii?Q?Y+RJiEqYia5Wrn2Rj84jtSQ0zHwTjYZq7yCe4gvzICjJmzxSuBULkKVdk3/j?= =?us-ascii?Q?8pyoOeJmMXqEFtnT+0c1LoCefi6i1y/bkwh9IpY56hOCkn8ApJlgEqklzx+3?= =?us-ascii?Q?31dxpTbCv45qwMe0j+KUieHnnKsxEGxTeyBqreEp4+iNPgkFOy0qIil5eBjt?= =?us-ascii?Q?vrwyWmcUC7yFwI9qTFFQoakEeudHDdVeIaYCw4oeeGgb9tOxQlJDNfnUV7Y8?= =?us-ascii?Q?EPHCuARU8fI9PBd96qjEdIfY5aoJ9kWV28HTTm4SBCshKHMRAN+Mk/v/NZSb?= =?us-ascii?Q?YqsmOUe0YDVD/J7Ee04NmA/CA4fbIunUEiuvEjr7G4qnrVjEeuygyQCaMm51?= =?us-ascii?Q?m9p2zTpp2QEwjaXPKqMjhVDtiYz9dnXsMJVPt8inipsPmvrx1m1LNYWFILaZ?= =?us-ascii?Q?HjiGekZLDNK7kGJ4J08ABRwdqQA1+UJvwjWinz+rHEImtzOHoqv+i4R4dBHb?= =?us-ascii?Q?sgjILey9DuRhAI4YBl4Sur5/oVHwNwuR37itNX2SvZ3HX1GUlEa/MACHvy9n?= =?us-ascii?Q?gzFEn4rDdD8JMJ0tRb0p7mE+sck5efLuzDBt7DMrKGExO61qSMZdDr1FY7G9?= =?us-ascii?Q?Bv/bdLaJLhRcHt2+9m70ldOxslCZKASqTHSrcsfC4kPOS/scPRJWIZjnYZES?= =?us-ascii?Q?kjEmJAF9O5lQ/Ft0/n7wWPj4PHdKsiX84boToLs3DywXX+GIkixpc4me4r2V?= =?us-ascii?Q?oA8yBa/ckStkonmT7HICO7urUMH5rQUXQ76UQQjtnYOX71eh16MsZL5pZciz?= =?us-ascii?Q?uDNXlxeSIxYAoND/Gc6flnSAlmEx1xR2rNW9d4CRmhIad92/NebhGHt6uLTY?= =?us-ascii?Q?CIAKrL+CxCYEVJ7a+ec/gaUOX/zJ0xUFw7NMiTQGQGSr9+MB+ipiLS41sSwN?= =?us-ascii?Q?PFl4B1F6g6S8p2+7MB/SicM0T0ZJ3Mlyp1rPCDtR2b5DwjdWmT4PfX5tMrBP?= =?us-ascii?Q?1Efg32uvMKLh4l4j9B7lPARvJmM58?= X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; SN2PR0701MB1023; 6:5Ihm5NTUlgOJRsvB7falvp4iiErvASeGi3Ogc+aG?= =?us-ascii?Q?FoLoLcwSULD54JJ9RHEBXyzbzZnQBd/NK7rTzLdH8SbdXab3CF/3yPmRIjaZ?= =?us-ascii?Q?dUBi+sWxp4sPNNaYvaW4wnEtwyux77hZg4FQMzYMepGHPsjEKrwncV+fuhQB?= =?us-ascii?Q?po/8CzA2W9YBWIr4QrFHmXmS3iFUvY+DUF7MzatxDtgGh+HIL8cUmpO7lQpq?= =?us-ascii?Q?vKAVMjEeuR1v8wLgRrrE+sCgKOuMCsnE62rYNMiYPp4IEJR9te5uYMDAalqq?= =?us-ascii?Q?QhuRj0HpTfu9HaRasY2ZjkjScdPYzsehd45ml+L2rQkApX43f+f090oHb+dM?= =?us-ascii?Q?f+UBlGshstOZz7Ny5iGHC6hqy5hzMHk2EcCKI6CI/h0OH2WX1dWo6eKMd0J+?= =?us-ascii?Q?xpuroUKOm2magBSJ9W6iMiokULjU5A0g00lO3CjEFDL8FAGQXK9kny6Btyu/?= =?us-ascii?Q?nNpO9IF3wXGhiaQuTSXf9bDMvpiXe51iOHqe2VDAWMEsBQg/R1u5YexjYMdO?= =?us-ascii?Q?gg5uwseu6gRDberpwOXjUgSmXmW3c45V0ec8zR7eF6zzas++L6HhBGBEzlKC?= =?us-ascii?Q?fa8M4maD0AadT80lJtFtP6+wwHBdcj9B9XGh2rOVPy0ehb5l74UHmARdJak+?= =?us-ascii?Q?fwocqQm7owgMJpzu+XENgInj3cmiReF0yUpjEmw2G0MMvAU3F6RKQLOm04jx?= =?us-ascii?Q?y/7PL0Sa3307jdtj7R8ql6iZQvkDdZywKyyEGF2fi1w6rwdQZAOuEE9OyTCu?= =?us-ascii?Q?B4XDyo463bTDkOLrc7Eb0tIHJ3EJ3TR26ZwQVHAuQpLcyZwcd3MgjPiwVOP4?= =?us-ascii?Q?zdYQm/OFpyJAJqftPWwVf/301jOvJ2Dg1Xk4F94hL6jDXa0J5u7a8x7ESP/3?= =?us-ascii?Q?kbmt9OvyX7quJCi7qktQ5NROkjAQTvLO7XKzdkB5QZlwLORxXePJbnXpjE3z?= =?us-ascii?Q?KBTaK2ZZ7V2DRWAcbYikfPYtdLZK++xs9WGeyc47sRJ0Obr345IlABOtf3vq?= =?us-ascii?Q?7Cs=3D?= X-Microsoft-Exchange-Diagnostics: 1; SN2PR0701MB1023; 5:I8gzRLGi3J4/tNXwFMvYjkA0dHVRiXiZpncowft8a6+ZJn5TdlWLoJ1Qwq3X2DiMOo8J4LtcVNZQl0AZX7WTNkvIl4lwvrrSPTZkbHAEMGWFqJPBzgP3nPNWaQRgKek0oovAAaTAzhavRjc5DXS0nVfNXQy/T+eh+GU8AL7j1jHuFnqgFc3/0+iMpkCZJATWsshd0ODAoxg1diGuu7fKRsO0mfm7BojGv1r+zAOjPKYlXRzER1AWofo1Uj8LVqKtJomuu3uvu03y7fg8l7bwkNNcvFVVWPdzxleYXo8Kb6SlCEnjxO1DBlc55sx488NAxieXRPj5xTV3CQaWYD6YcmawCWRXpNFZyS6qDHhhd2adnALdxiPQtIZES00JffdkE07DOngFli1JzyQp+hu7MK4ZIBVZmn9regENdJZq1qwtVlb8Hsz2R0SzMcAHjjILFX6CjoKvm5jeRKVMkgV0ttoaJgVxwhjdxAucsqvEcn/w0Mm0iWcloMGk979z3n81; 24:aJGNBYKw4fli7c820mFkqWJf274xcSEXChaMbhRONLQTb+PR1UwFv2Pi/FBa/sGFf/cX9z4mjXoaOQrhSL7Or3YcWCy6wQzhnBdjsK8Bltg= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; SN2PR0701MB1023; 7:GMh6w+MYC5GqGn2ZMamAA4bzjO+/QaDKGnMfNaVwPZCvybXf6VA4qQibnP9yBzGXpwsHBkHFPc/R08KblLOt8TcxZqMSjmBXQchYlt4x69egy7Rsbbvh3JaZoucwZYZ7Lzo1uMDIagdSTn1/SO/IJaatL+wFoJIc3e2BXtz91ucidi5SIrog7pvC+ZVng9tShrDXul6IZntZhmhM2MF7LB+87NyOv6H+GKsKQ17498bSFQhrrcVMVxzWpO2jeZ11iJEtVxQHhmZOlpWkQfjXLrBdLiE2xSuOuFNV7qO1cSvjb98dNYG6k6hELVm2cmI+mtL6g8SKGIcFGsyFfxoH9SXDs+PwZ3IC0MznRhVFW0yTK+J028Yg2taukBO9km2XnyIV3uhliSsRRwc0W9F01nZEb0WHj8VnrLjERKs6LXFtWWalVuhJWsfhINtQVSshueOdfMrb1r0AP9Wb3lyVEKTcF9oxubRSFUU4kEDbHq5+HPHubs671ibs5WqytojdsEQpqXi/Cs8e2DxB76Rxk/wu7FWWxnoPY18ZWMYpsdaB8AuBrkcCDn5Lb8lUHW1YmsxW2BbI41PVDBPdSvP7NZjqpL0QU850Yei9SdI6L/H3QO3uIy+UplHxyv+EZWr7wqiPj8Xjk5DkKNiGXTYUmJf788UqL4LN9AsoLYq9Xp6H7B5jMU6CDfHa1bWOut1NSGWarTPs33diFM3hFZtmVYyfEk6VJQtxxch1dSaELnW6bl8viL7yofx9Z2EjRRgIjVfSYOa/qh1q92nhp5wQbfwaZOIqZO34RMM9AZJZbVU= X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jun 2017 18:15:50.1209 (UTC) X-MS-Exchange-CrossTenant-Id: 711e4ccf-2e9b-4bcf-a551-4094005b6194 X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=711e4ccf-2e9b-4bcf-a551-4094005b6194; Ip=[50.232.66.26]; Helo=[CAEXCH02.caveonetworks.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN2PR0701MB1023 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 Implements the iWARP connection management functions: connect, accept, create listener and destroy listener Signed-off-by: Michal Kalderon Signed-off-by: Ram Amrani Signed-off-by: Ariel Elior --- drivers/infiniband/hw/qedr/main.c | 11 + drivers/infiniband/hw/qedr/qedr.h | 21 +- drivers/infiniband/hw/qedr/qedr_iw_cm.c | 689 ++++++++++++++++++++++++++++++++ drivers/infiniband/hw/qedr/qedr_iw_cm.h | 12 + drivers/infiniband/hw/qedr/verbs.c | 17 + 5 files changed, 749 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c index ebac63f..c594b11 100644 --- a/drivers/infiniband/hw/qedr/main.c +++ b/drivers/infiniband/hw/qedr/main.c @@ -145,6 +145,12 @@ int qedr_iw_register_device(struct qedr_dev *dev) dev->ibdev.iwcm = kzalloc(sizeof(*dev->ibdev.iwcm), GFP_KERNEL); if (!dev->ibdev.iwcm) return -ENOMEM; + + dev->ibdev.iwcm->connect = qedr_iw_connect; + dev->ibdev.iwcm->accept = qedr_iw_accept; + dev->ibdev.iwcm->reject = qedr_iw_reject; + dev->ibdev.iwcm->create_listen = qedr_iw_create_listen; + dev->ibdev.iwcm->destroy_listen = qedr_iw_destroy_listen; dev->ibdev.iwcm->add_ref = qedr_iw_qp_add_ref; dev->ibdev.iwcm->rem_ref = qedr_iw_qp_rem_ref; dev->ibdev.iwcm->get_qp = qedr_iw_get_qp; @@ -296,6 +302,9 @@ static void qedr_free_resources(struct qedr_dev *dev) { int i; + if (IS_IWARP(dev)) + destroy_workqueue(dev->iwarp_wq); + for (i = 0; i < dev->num_cnq; i++) { qedr_free_mem_sb(dev, &dev->sb_array[i], dev->sb_start + i); dev->ops->common->chain_free(dev->cdev, &dev->cnq_array[i].pbl); @@ -323,6 +332,7 @@ static int qedr_alloc_resources(struct qedr_dev *dev) if (IS_IWARP(dev)) { spin_lock_init(&dev->idr_lock); idr_init(&dev->qpidr); + dev->iwarp_wq = create_singlethread_workqueue("qedr_iwarpq"); } /* Allocate Status blocks for CNQ */ @@ -800,6 +810,7 @@ static int qedr_init_hw(struct qedr_dev *dev) in_params->events = &events; in_params->cq_mode = QED_RDMA_CQ_MODE_32_BITS; in_params->max_mtu = dev->ndev->mtu; + dev->iwarp_max_mtu = dev->ndev->mtu; ether_addr_copy(&in_params->mac_addr[0], dev->ndev->dev_addr); rc = dev->ops->rdma_init(dev->cdev, in_params); diff --git a/drivers/infiniband/hw/qedr/qedr.h b/drivers/infiniband/hw/qedr/qedr.h index 5dd82d1..7c7183a 100644 --- a/drivers/infiniband/hw/qedr/qedr.h +++ b/drivers/infiniband/hw/qedr/qedr.h @@ -60,6 +60,7 @@ #define QEDR_MSG_SQ " SQ" #define QEDR_MSG_QP " QP" #define QEDR_MSG_GSI " GSI" +#define QEDR_MSG_IWARP " IW" #define QEDR_CQ_MAGIC_NUMBER (0x11223344) @@ -167,6 +168,8 @@ struct qedr_dev { enum qed_rdma_type rdma_type; spinlock_t idr_lock; /* Protect qpidr data-structure */ struct idr qpidr; + struct workqueue_struct *iwarp_wq; + u16 iwarp_max_mtu; unsigned long enet_state; }; @@ -344,7 +347,7 @@ enum qedr_qp_err_bitmap { struct qedr_qp { struct ib_qp ibqp; /* must be first */ struct qedr_dev *dev; - + struct qedr_iw_ep *ep; struct qedr_qp_hwq_info sq; struct qedr_qp_hwq_info rq; @@ -402,6 +405,7 @@ struct qedr_qp { struct qedr_userq usq; struct qedr_userq urq; atomic_t refcnt; + bool destroyed; }; struct qedr_ah { @@ -482,6 +486,21 @@ static inline int qedr_get_dmac(struct qedr_dev *dev, return 0; } +struct qedr_iw_listener { + struct qedr_dev *dev; + struct iw_cm_id *cm_id; + int backlog; + void *qed_handle; +}; + +struct qedr_iw_ep { + struct qedr_dev *dev; + struct iw_cm_id *cm_id; + struct qedr_qp *qp; + void *qed_context; + u8 during_connect; +}; + static inline struct qedr_ucontext *get_qedr_ucontext(struct ib_ucontext *ibucontext) { diff --git a/drivers/infiniband/hw/qedr/qedr_iw_cm.c b/drivers/infiniband/hw/qedr/qedr_iw_cm.c index 8811dbc..fe9b2b6 100644 --- a/drivers/infiniband/hw/qedr/qedr_iw_cm.c +++ b/drivers/infiniband/hw/qedr/qedr_iw_cm.c @@ -29,7 +29,696 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ +#include +#include +#include +#include +#include +#include +#include #include "qedr.h" +#include "qedr_iw_cm.h" + +static inline void +qedr_fill_sockaddr4(const struct qed_iwarp_cm_info *cm_info, + struct iw_cm_event *event) +{ + struct sockaddr_in *laddr = (struct sockaddr_in *)&event->local_addr; + struct sockaddr_in *raddr = (struct sockaddr_in *)&event->remote_addr; + + laddr->sin_family = AF_INET; + raddr->sin_family = AF_INET; + + laddr->sin_port = htons(cm_info->local_port); + raddr->sin_port = htons(cm_info->remote_port); + + laddr->sin_addr.s_addr = htonl(cm_info->local_ip[0]); + raddr->sin_addr.s_addr = htonl(cm_info->remote_ip[0]); +} + +static inline void +qedr_fill_sockaddr6(const struct qed_iwarp_cm_info *cm_info, + struct iw_cm_event *event) +{ + struct sockaddr_in6 *laddr6 = (struct sockaddr_in6 *)&event->local_addr; + struct sockaddr_in6 *raddr6 = + (struct sockaddr_in6 *)&event->remote_addr; + int i; + + laddr6->sin6_family = AF_INET6; + raddr6->sin6_family = AF_INET6; + + laddr6->sin6_port = htons(cm_info->local_port); + raddr6->sin6_port = htons(cm_info->remote_port); + + for (i = 0; i < 4; i++) { + laddr6->sin6_addr.in6_u.u6_addr32[i] = + htonl(cm_info->local_ip[i]); + raddr6->sin6_addr.in6_u.u6_addr32[i] = + htonl(cm_info->remote_ip[i]); + } +} + +void +qedr_iw_mpa_request(void *context, struct qed_iwarp_cm_event_params *params) +{ + struct qedr_iw_listener *listener = (struct qedr_iw_listener *)context; + struct qedr_dev *dev = listener->dev; + struct iw_cm_event event; + struct qedr_iw_ep *ep; + + ep = kzalloc(sizeof(*ep), GFP_ATOMIC); + if (!ep) + return; + + ep->dev = dev; + ep->qed_context = params->ep_context; + + memset(&event, 0, sizeof(event)); + event.event = IW_CM_EVENT_CONNECT_REQUEST; + event.status = params->status; + + if (params->cm_info->ip_version == QED_TCP_IPV4) + qedr_fill_sockaddr4(params->cm_info, &event); + else + qedr_fill_sockaddr6(params->cm_info, &event); + + event.provider_data = (void *)ep; + event.private_data = (void *)params->cm_info->private_data; + event.private_data_len = (u8)params->cm_info->private_data_len; + event.ord = params->cm_info->ord; + event.ird = params->cm_info->ird; + + listener->cm_id->event_handler(listener->cm_id, &event); +} + +void +qedr_iw_issue_event(void *context, + struct qed_iwarp_cm_event_params *params, + enum iw_cm_event_type event_type) +{ + struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context; + struct iw_cm_event event; + + memset(&event, 0, sizeof(event)); + event.status = params->status; + event.event = event_type; + + if (params->cm_info) { + event.ird = params->cm_info->ird; + event.ord = params->cm_info->ord; + event.private_data_len = params->cm_info->private_data_len; + event.private_data = (void *)params->cm_info->private_data; + } + + if (ep->cm_id) + ep->cm_id->event_handler(ep->cm_id, &event); +} + +void +qedr_iw_close_event(void *context, struct qed_iwarp_cm_event_params *params) +{ + struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context; + + if (ep->cm_id) { + qedr_iw_issue_event(context, params, IW_CM_EVENT_CLOSE); + + ep->cm_id->rem_ref(ep->cm_id); + ep->cm_id = NULL; + } +} + +void +qedr_iw_qp_event(void *context, + struct qed_iwarp_cm_event_params *params, + enum ib_event_type ib_event, char *str) +{ + struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context; + struct qedr_dev *dev = ep->dev; + struct ib_qp *ibqp = &ep->qp->ibqp; + struct ib_event event; + + DP_NOTICE(dev, "QP error received: %s\n", str); + + if (ibqp->event_handler) { + event.event = ib_event; + event.device = ibqp->device; + event.element.qp = ibqp; + ibqp->event_handler(&event, ibqp->qp_context); + } +} + +struct qedr_discon_work { + struct work_struct work; + struct qedr_iw_ep *ep; + enum qed_iwarp_event_type event; + int status; +}; + +static void qedr_iw_disconnect_worker(struct work_struct *work) +{ + struct qedr_discon_work *dwork = + container_of(work, struct qedr_discon_work, work); + struct qed_rdma_modify_qp_in_params qp_params = { 0 }; + struct qedr_iw_ep *ep = dwork->ep; + struct qedr_dev *dev = ep->dev; + struct qedr_qp *qp = ep->qp; + struct iw_cm_event event; + + if (qp->destroyed) { + kfree(dwork); + qedr_iw_qp_rem_ref(&qp->ibqp); + return; + } + + memset(&event, 0, sizeof(event)); + event.status = dwork->status; + event.event = IW_CM_EVENT_DISCONNECT; + + /* Success means graceful disconnect was requested. modifying + * to SQD is translated to graceful disconnect. O/w reset is sent + */ + if (dwork->status) + qp_params.new_state = QED_ROCE_QP_STATE_ERR; + else + qp_params.new_state = QED_ROCE_QP_STATE_SQD; + + kfree(dwork); + + if (ep->cm_id) + ep->cm_id->event_handler(ep->cm_id, &event); + + SET_FIELD(qp_params.modify_flags, + QED_RDMA_MODIFY_QP_VALID_NEW_STATE, 1); + + dev->ops->rdma_modify_qp(dev->rdma_ctx, qp->qed_qp, &qp_params); + + qedr_iw_qp_rem_ref(&qp->ibqp); +} + +void +qedr_iw_disconnect_event(void *context, + struct qed_iwarp_cm_event_params *params) +{ + struct qedr_discon_work *work; + struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context; + struct qedr_dev *dev = ep->dev; + struct qedr_qp *qp = ep->qp; + + work = kzalloc(sizeof(*work), GFP_ATOMIC); + if (!work) + return; + + qedr_iw_qp_add_ref(&qp->ibqp); + work->ep = ep; + work->event = params->event; + work->status = params->status; + + INIT_WORK(&work->work, qedr_iw_disconnect_worker); + queue_work(dev->iwarp_wq, &work->work); +} + +static void +qedr_iw_passive_complete(void *context, + struct qed_iwarp_cm_event_params *params) +{ + struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context; + struct qedr_dev *dev = ep->dev; + + /* We will only reach the following state if MPA_REJECT was called on + * passive. In this case there will be no associated QP. + */ + if ((params->status == -ECONNREFUSED) && (!ep->qp)) { + DP_DEBUG(dev, QEDR_MSG_IWARP, + "PASSIVE connection refused releasing ep...\n"); + kfree(ep); + return; + } + + qedr_iw_issue_event(context, params, IW_CM_EVENT_ESTABLISHED); + + if (params->status < 0) + qedr_iw_close_event(context, params); +} + +int +qedr_iw_mpa_reply(void *context, struct qed_iwarp_cm_event_params *params) +{ + struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context; + struct qedr_dev *dev = ep->dev; + struct qed_iwarp_send_rtr_in rtr_in; + + rtr_in.ep_context = params->ep_context; + + return dev->ops->iwarp_send_rtr(dev->rdma_ctx, &rtr_in); +} + +int +qedr_iw_event_handler(void *context, struct qed_iwarp_cm_event_params *params) +{ + struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context; + struct qedr_dev *dev = ep->dev; + + switch (params->event) { + case QED_IWARP_EVENT_MPA_REQUEST: + qedr_iw_mpa_request(context, params); + break; + case QED_IWARP_EVENT_ACTIVE_MPA_REPLY: + qedr_iw_mpa_reply(context, params); + break; + case QED_IWARP_EVENT_PASSIVE_COMPLETE: + ep->during_connect = 0; + qedr_iw_passive_complete(context, params); + break; + + case QED_IWARP_EVENT_ACTIVE_COMPLETE: + ep->during_connect = 0; + qedr_iw_issue_event(context, + params, + IW_CM_EVENT_CONNECT_REPLY); + if (params->status < 0) { + struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context; + + ep->cm_id->rem_ref(ep->cm_id); + ep->cm_id = NULL; + } + break; + case QED_IWARP_EVENT_DISCONNECT: + qedr_iw_disconnect_event(context, params); + break; + case QED_IWARP_EVENT_CLOSE: + ep->during_connect = 0; + qedr_iw_close_event(context, params); + break; + case QED_IWARP_EVENT_RQ_EMPTY: + qedr_iw_qp_event(context, params, IB_EVENT_QP_FATAL, + "QED_IWARP_EVENT_RQ_EMPTY"); + break; + case QED_IWARP_EVENT_IRQ_FULL: + qedr_iw_qp_event(context, params, IB_EVENT_QP_FATAL, + "QED_IWARP_EVENT_IRQ_FULL"); + break; + case QED_IWARP_EVENT_LLP_TIMEOUT: + qedr_iw_qp_event(context, params, IB_EVENT_QP_FATAL, + "QED_IWARP_EVENT_LLP_TIMEOUT"); + break; + case QED_IWARP_EVENT_REMOTE_PROTECTION_ERROR: + qedr_iw_qp_event(context, params, IB_EVENT_QP_ACCESS_ERR, + "QED_IWARP_EVENT_REMOTE_PROTECTION_ERROR"); + break; + case QED_IWARP_EVENT_CQ_OVERFLOW: + qedr_iw_qp_event(context, params, IB_EVENT_QP_FATAL, + "QED_IWARP_EVENT_CQ_OVERFLOW"); + break; + case QED_IWARP_EVENT_QP_CATASTROPHIC: + qedr_iw_qp_event(context, params, IB_EVENT_QP_FATAL, + "QED_IWARP_EVENT_QP_CATASTROPHIC"); + break; + case QED_IWARP_EVENT_LOCAL_ACCESS_ERROR: + qedr_iw_qp_event(context, params, IB_EVENT_QP_ACCESS_ERR, + "QED_IWARP_EVENT_LOCAL_ACCESS_ERROR"); + break; + case QED_IWARP_EVENT_REMOTE_OPERATION_ERROR: + qedr_iw_qp_event(context, params, IB_EVENT_QP_FATAL, + "QED_IWARP_EVENT_REMOTE_OPERATION_ERROR"); + break; + case QED_IWARP_EVENT_TERMINATE_RECEIVED: + DP_NOTICE(dev, "Got terminate message\n"); + break; + default: + DP_NOTICE(dev, "Unknown event received %d\n", params->event); + break; + }; + return 0; +} + +static u16 qedr_iw_get_vlan_ipv4(struct qedr_dev *dev, u32 *addr) +{ + struct net_device *ndev; + u16 vlan_id = 0; + + ndev = ip_dev_find(&init_net, htonl(addr[0])); + + if (ndev) { + vlan_id = rdma_vlan_dev_vlan_id(ndev); + dev_put(ndev); + } + if (vlan_id == 0xffff) + vlan_id = 0; + return vlan_id; +} + +static u16 qedr_iw_get_vlan_ipv6(u32 *addr) +{ + struct net_device *ndev = NULL; + struct in6_addr laddr6; + u16 vlan_id = 0; + int i; + + if (!IS_ENABLED(CONFIG_IPV6)) + return vlan_id; + + for (i = 0; i < 4; i++) + laddr6.in6_u.u6_addr32[i] = htonl(addr[i]); + + rcu_read_lock(); + for_each_netdev_rcu(&init_net, ndev) { + if (ipv6_chk_addr(&init_net, &laddr6, ndev, 1)) { + vlan_id = rdma_vlan_dev_vlan_id(ndev); + break; + } + } + + rcu_read_unlock(); + if (vlan_id == 0xffff) + vlan_id = 0; + + return vlan_id; +} + +static int +qedr_addr4_resolve(struct qedr_dev *dev, + struct sockaddr_in *src_in, + struct sockaddr_in *dst_in, u8 *dst_mac) +{ + __be32 src_ip = src_in->sin_addr.s_addr; + __be32 dst_ip = dst_in->sin_addr.s_addr; + struct neighbour *neigh = NULL; + struct rtable *rt = NULL; + int rc = 0; + + rt = ip_route_output(&init_net, dst_ip, src_ip, 0, 0); + if (IS_ERR(rt)) { + DP_ERR(dev, "ip_route_output returned error\n"); + return -EINVAL; + } + + neigh = dst_neigh_lookup(&rt->dst, &dst_ip); + + if (neigh) { + rcu_read_lock(); + if (neigh->nud_state & NUD_VALID) { + ether_addr_copy(dst_mac, neigh->ha); + DP_DEBUG(dev, QEDR_MSG_QP, "mac_addr=[%pM]\n", dst_mac); + } else { + neigh_event_send(neigh, NULL); + } + rcu_read_unlock(); + neigh_release(neigh); + } + + ip_rt_put(rt); + + return rc; +} + +static int +qedr_addr6_resolve(struct qedr_dev *dev, + struct sockaddr_in6 *src_in, + struct sockaddr_in6 *dst_in, u8 *dst_mac) +{ + struct neighbour *neigh = NULL; + struct dst_entry *dst; + struct flowi6 fl6; + int rc = 0; + + memset(&fl6, 0, sizeof(fl6)); + fl6.daddr = dst_in->sin6_addr; + fl6.saddr = src_in->sin6_addr; + + dst = ip6_route_output(&init_net, NULL, &fl6); + + if ((!dst) || dst->error) { + if (dst) { + dst_release(dst); + DP_ERR(dev, + "ip6_route_output returned dst->error = %d\n", + dst->error); + } + return -EINVAL; + } + neigh = dst_neigh_lookup(dst, &dst_in); + + if (neigh) { + rcu_read_lock(); + if (neigh->nud_state & NUD_VALID) { + ether_addr_copy(dst_mac, neigh->ha); + DP_DEBUG(dev, QEDR_MSG_QP, "mac_addr=[%pM]\n", dst_mac); + } else { + neigh_event_send(neigh, NULL); + } + rcu_read_unlock(); + neigh_release(neigh); + } + + dst_release(dst); + + return rc; +} + +int qedr_iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) +{ + struct qedr_dev *dev = get_qedr_dev(cm_id->device); + struct qed_iwarp_connect_out out_params; + struct qed_iwarp_connect_in in_params; + struct qed_iwarp_cm_info *cm_info; + struct sockaddr_in6 *laddr6; + struct sockaddr_in6 *raddr6; + struct sockaddr_in *laddr; + struct sockaddr_in *raddr; + struct qedr_iw_ep *ep; + struct qedr_qp *qp; + int rc = 0; + int i; + + qp = idr_find(&dev->qpidr, conn_param->qpn); + + laddr = (struct sockaddr_in *)&cm_id->local_addr; + raddr = (struct sockaddr_in *)&cm_id->remote_addr; + laddr6 = (struct sockaddr_in6 *)&cm_id->local_addr; + raddr6 = (struct sockaddr_in6 *)&cm_id->remote_addr; + + DP_DEBUG(dev, QEDR_MSG_IWARP, + "Connect source address: %pISpc, remote address: %pISpc\n", + &cm_id->local_addr, &cm_id->remote_addr); + + if (!laddr->sin_port || !raddr->sin_port) + return -EINVAL; + + ep = kzalloc(sizeof(*ep), GFP_KERNEL); + if (!ep) + return -ENOMEM; + + ep->dev = dev; + ep->qp = qp; + qp->ep = ep; + cm_id->add_ref(cm_id); + ep->cm_id = cm_id; + + in_params.event_cb = qedr_iw_event_handler; + in_params.cb_context = ep; + + cm_info = &in_params.cm_info; + memset(cm_info->local_ip, 0, sizeof(cm_info->local_ip)); + memset(cm_info->remote_ip, 0, sizeof(cm_info->remote_ip)); + + if (cm_id->remote_addr.ss_family == AF_INET) { + cm_info->ip_version = QED_TCP_IPV4; + + cm_info->remote_ip[0] = ntohl(raddr->sin_addr.s_addr); + cm_info->local_ip[0] = ntohl(laddr->sin_addr.s_addr); + cm_info->remote_port = ntohs(raddr->sin_port); + cm_info->local_port = ntohs(laddr->sin_port); + cm_info->vlan = qedr_iw_get_vlan_ipv4(dev, cm_info->local_ip); + + rc = qedr_addr4_resolve(dev, laddr, raddr, + (u8 *)in_params.remote_mac_addr); + + in_params.mss = dev->iwarp_max_mtu - + (sizeof(struct iphdr) + sizeof(struct tcphdr)); + + } else { + in_params.cm_info.ip_version = QED_TCP_IPV6; + + for (i = 0; i < 4; i++) { + cm_info->remote_ip[i] = + ntohl(raddr6->sin6_addr.in6_u.u6_addr32[i]); + cm_info->local_ip[i] = + ntohl(laddr6->sin6_addr.in6_u.u6_addr32[i]); + } + + cm_info->local_port = ntohs(laddr6->sin6_port); + cm_info->remote_port = ntohs(raddr6->sin6_port); + + in_params.mss = dev->iwarp_max_mtu - + (sizeof(struct ipv6hdr) + sizeof(struct tcphdr)); + + cm_info->vlan = qedr_iw_get_vlan_ipv6(cm_info->local_ip); + + rc = qedr_addr6_resolve(dev, laddr6, raddr6, + (u8 *)in_params.remote_mac_addr); + } + if (rc) + goto err; + + DP_DEBUG(dev, QEDR_MSG_IWARP, + "ord = %d ird=%d private_data=%p private_data_len=%d rq_psn=%d\n", + conn_param->ord, conn_param->ird, conn_param->private_data, + conn_param->private_data_len, qp->rq_psn); + + cm_info->ord = conn_param->ord; + cm_info->ird = conn_param->ird; + cm_info->private_data = conn_param->private_data; + cm_info->private_data_len = conn_param->private_data_len; + in_params.qp = qp->qed_qp; + memcpy(in_params.local_mac_addr, dev->ndev->dev_addr, ETH_ALEN); + + ep->during_connect = 1; + rc = dev->ops->iwarp_connect(dev->rdma_ctx, &in_params, &out_params); + if (rc) + goto err; + + return rc; + +err: + cm_id->rem_ref(cm_id); + kfree(ep); + return rc; +} + +int qedr_iw_create_listen(struct iw_cm_id *cm_id, int backlog) +{ + struct qedr_dev *dev = get_qedr_dev(cm_id->device); + struct qedr_iw_listener *listener; + struct qed_iwarp_listen_in iparams; + struct qed_iwarp_listen_out oparams; + struct sockaddr_in *laddr; + struct sockaddr_in6 *laddr6; + int rc; + int i; + + laddr = (struct sockaddr_in *)&cm_id->local_addr; + laddr6 = (struct sockaddr_in6 *)&cm_id->local_addr; + + DP_DEBUG(dev, QEDR_MSG_IWARP, + "Create Listener address: %pISpc\n", &cm_id->local_addr); + + listener = kzalloc(sizeof(*listener), GFP_KERNEL); + if (!listener) + return -ENOMEM; + + listener->dev = dev; + cm_id->add_ref(cm_id); + listener->cm_id = cm_id; + listener->backlog = backlog; + + iparams.cb_context = listener; + iparams.event_cb = qedr_iw_event_handler; + iparams.max_backlog = backlog; + + if (cm_id->local_addr.ss_family == AF_INET) { + iparams.ip_version = QED_TCP_IPV4; + memset(iparams.ip_addr, 0, sizeof(iparams.ip_addr)); + + iparams.ip_addr[0] = ntohl(laddr->sin_addr.s_addr); + iparams.port = ntohs(laddr->sin_port); + iparams.vlan = qedr_iw_get_vlan_ipv4(dev, iparams.ip_addr); + } else { + iparams.ip_version = QED_TCP_IPV6; + + for (i = 0; i < 4; i++) { + iparams.ip_addr[i] = + ntohl(laddr6->sin6_addr.in6_u.u6_addr32[i]); + } + + iparams.port = ntohs(laddr6->sin6_port); + + iparams.vlan = qedr_iw_get_vlan_ipv6(iparams.ip_addr); + } + rc = dev->ops->iwarp_create_listen(dev->rdma_ctx, &iparams, &oparams); + if (rc) + goto err; + + listener->qed_handle = oparams.handle; + cm_id->provider_data = listener; + return rc; + +err: + cm_id->rem_ref(cm_id); + kfree(listener); + return rc; +} + +int qedr_iw_destroy_listen(struct iw_cm_id *cm_id) +{ + struct qedr_iw_listener *listener = cm_id->provider_data; + struct qedr_dev *dev = get_qedr_dev(cm_id->device); + int rc = 0; + + if (listener->qed_handle) + rc = dev->ops->iwarp_destroy_listen(dev->rdma_ctx, + listener->qed_handle); + + cm_id->rem_ref(cm_id); + return rc; +} + +int qedr_iw_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) +{ + struct qedr_iw_ep *ep = (struct qedr_iw_ep *)cm_id->provider_data; + struct qedr_dev *dev = ep->dev; + struct qedr_qp *qp; + struct qed_iwarp_accept_in params; + int rc; + + DP_DEBUG(dev, QEDR_MSG_IWARP, "Accept on qpid=%d\n", conn_param->qpn); + + qp = idr_find(&dev->qpidr, conn_param->qpn); + if (!qp) { + DP_ERR(dev, "Invalid QP number %d\n", conn_param->qpn); + return -EINVAL; + } + + ep->qp = qp; + qp->ep = ep; + cm_id->add_ref(cm_id); + ep->cm_id = cm_id; + + params.ep_context = ep->qed_context; + params.cb_context = ep; + params.qp = ep->qp->qed_qp; + params.private_data = conn_param->private_data; + params.private_data_len = conn_param->private_data_len; + params.ird = conn_param->ird; + params.ord = conn_param->ord; + + ep->during_connect = 1; + rc = dev->ops->iwarp_accept(dev->rdma_ctx, ¶ms); + if (rc) + goto err; + + return rc; +err: + ep->during_connect = 0; + cm_id->rem_ref(cm_id); + return rc; +} + +int qedr_iw_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) +{ + struct qedr_iw_ep *ep = (struct qedr_iw_ep *)cm_id->provider_data; + struct qedr_dev *dev = ep->dev; + struct qed_iwarp_reject_in params; + + params.ep_context = ep->qed_context; + params.cb_context = ep; + params.private_data = pdata; + params.private_data_len = pdata_len; + ep->qp = NULL; + + return dev->ops->iwarp_reject(dev->rdma_ctx, ¶ms); +} + void qedr_iw_qp_add_ref(struct ib_qp *ibqp) { struct qedr_qp *qp = get_qedr_qp(ibqp); diff --git a/drivers/infiniband/hw/qedr/qedr_iw_cm.h b/drivers/infiniband/hw/qedr/qedr_iw_cm.h index ea6d17af..08f4b10 100644 --- a/drivers/infiniband/hw/qedr/qedr_iw_cm.h +++ b/drivers/infiniband/hw/qedr/qedr_iw_cm.h @@ -30,6 +30,18 @@ * SOFTWARE. */ #include + +int qedr_iw_connect(struct iw_cm_id *cm_id, + struct iw_cm_conn_param *conn_param); + +int qedr_iw_create_listen(struct iw_cm_id *cm_id, int backlog); + +int qedr_iw_destroy_listen(struct iw_cm_id *cm_id); + +int qedr_iw_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param); + +int qedr_iw_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len); + void qedr_iw_qp_add_ref(struct ib_qp *qp); void qedr_iw_qp_rem_ref(struct ib_qp *qp); diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index cccae13..229c63e 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c @@ -2249,6 +2249,23 @@ int qedr_destroy_qp(struct ib_qp *ibqp) /* Change the QP state to ERROR */ qedr_modify_qp(ibqp, &attr, attr_mask, NULL); } + } else { + /* Wait for the connect/accept to complete */ + if (qp->ep) { + int wait_count = 1; + + while (qp->ep->during_connect) { + DP_DEBUG(dev, QEDR_MSG_QP, + "Still in during connect/accept\n"); + + msleep(100); + if (wait_count++ > 200) { + DP_NOTICE(dev, + "during connect timeout\n"); + break; + } + } + } } if (qp->qp_type == IB_QPT_GSI)