From patchwork Tue Jan 5 14:26:49 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bart Van Assche X-Patchwork-Id: 7955401 Return-Path: X-Original-To: patchwork-linux-rdma@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 4ED079F38D for ; Tue, 5 Jan 2016 14:27:02 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id ADBBA20384 for ; Tue, 5 Jan 2016 14:27:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 053282037E for ; Tue, 5 Jan 2016 14:26:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751487AbcAEO06 (ORCPT ); Tue, 5 Jan 2016 09:26:58 -0500 Received: from mail-bn1bon0067.outbound.protection.outlook.com ([157.56.111.67]:21532 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751445AbcAEO04 (ORCPT ); Tue, 5 Jan 2016 09:26:56 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sandiskcorp.onmicrosoft.com; s=selector1-sandisk-com; h=From:To:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=hcxV/oPakcsa4HXrr0RDbWo/yN1OF1IZICc40VuuN5k=; b=q9EFQQ2cZFFQ2Cc/t6aJJo7pR1/II0E3nyjvxuDr3VZUssitHQ2fYgpv6sApE374VZIqtgGVcxb1MnCfPrE2CEXQq7Ain52jk+vmfMYPE10mdEeNw4hCeCLSE7uM9kZr6fYAMiIslvI/hYU/S9iyf6t9vxKvtq/DEsHfCNLqysw= Received: from BLUPR02CA029.namprd02.prod.outlook.com (10.160.23.147) by CY1PR0201MB0827.namprd02.prod.outlook.com (10.160.141.28) with Microsoft SMTP Server (TLS) id 15.1.361.13; Tue, 5 Jan 2016 14:26:52 +0000 Received: from BY2FFO11FD010.protection.gbl (2a01:111:f400:7c0c::105) by BLUPR02CA029.outlook.office365.com (2a01:111:e400:8ad::19) with Microsoft SMTP Server (TLS) id 15.1.361.13 via Frontend Transport; Tue, 5 Jan 2016 14:26:52 +0000 Authentication-Results: spf=pass (sender IP is 63.163.107.173) smtp.mailfrom=sandisk.com; redhat.com; dkim=none (message not signed) header.d=none;redhat.com; dmarc=bestguesspass action=none header.from=sandisk.com; Received-SPF: Pass (protection.outlook.com: domain of sandisk.com designates 63.163.107.173 as permitted sender) receiver=protection.outlook.com; client-ip=63.163.107.173; helo=milsmgep12.sandisk.com; Received: from milsmgep12.sandisk.com (63.163.107.173) by BY2FFO11FD010.mail.protection.outlook.com (10.1.14.74) with Microsoft SMTP Server id 15.1.355.15 via Frontend Transport; Tue, 5 Jan 2016 14:26:51 +0000 Received: from MILHUBIP04.sdcorp.global.sandisk.com ( [172.22.12.162]) by milsmgep12.sandisk.com (Symantec Messaging Gateway) with SMTP id 97.1E.02821.BA2DB865; Tue, 5 Jan 2016 06:26:51 -0800 (PST) Received: from milsmgip11.sandisk.com (10.177.8.100) by MILHUBIP04.sdcorp.global.sandisk.com (10.177.9.97) with Microsoft SMTP Server id 14.3.248.2; Tue, 5 Jan 2016 06:26:51 -0800 X-AuditID: ac160a69-f797e6d000000b05-26-568bd2ab7d21 Received: from [10.50.231.71] ( [10.177.8.100]) by milsmgip11.sandisk.com (Symantec Messaging Gateway) with SMTP id 31.0E.08831.9A2DB865; Tue, 5 Jan 2016 06:26:51 -0800 (PST) Subject: [PATCH 13/15] IB/srpt: Detect session shutdown reliably To: Doug Ledford References: <568BD0FC.70207@sandisk.com> CC: Christoph Hellwig , "linux-rdma@vger.kernel.org" From: Bart Van Assche Message-ID: <568BD2A9.6070600@sandisk.com> Date: Tue, 5 Jan 2016 15:26:49 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.5.0 MIME-Version: 1.0 In-Reply-To: <568BD0FC.70207@sandisk.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrLLMWRmVeSWpSXmKPExsWyRoxnke7qS91hBtfOiVq8PP+B1WLl6qNM Fs8O9bI4MHvsvtnA5vF+31U2j8+b5AKYo7hsUlJzMstSi/TtErgyrk/ezlLQV1XRuescewPj mqQuRg4OCQETiU2Pq7sYOYFMMYkL99azdTFycQgJnGCUWHJwApSznVHi1NMnLBBVJhJ3/q1l hUhsZpRo39XBDpIQFnCQODv7OZgtIqAmsenVInaQDUICGhLvtmaBhJkF4iXWfXrDCGKzCRhJ fHs/E2wmr4CWxJ8JJ5lAbBYBFYmN9x+ygtiiAhESPzYsYYSoEZQ4ORPiBk4BTYn/rbvAxjMD 2et36UOMl5fY/nYOM8hpEgLLWCWWvlgFVi8koC5xcsl8pgmMIrOQjJqF0D4LSfsCRuZVjGK5 mTnFuempBYZGesWJeSmZxdl6yfm5mxjBkcCVuYNxxSTzQ4wCHIxKPLwcL7vChFgTy4orcw8x SnAwK4nwvj7SHSbEm5JYWZValB9fVJqTWnyIUZqDRUmc17pFLUxIID2xJDU7NbUgtQgmy8TB KdXAyCNQ+9E7tf78n3k9FtOtMudd6PYy/JU2demVQMvEO/LyU/dMPW4c3zRnXd/HrsdrLU7t cpI7d+ml7RY3ncMqrhErpkYtzdh3MnLfV9lLnEwnj4er1uy+cyKHY7Kp0MWp2SmHj/BGMGqt XHH8e9TCXXoP1+q0ue3pXJldJPOzxsridWKnyrvFd5VYijMSDbWYi4oTAfOUVgKAAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrCJMWRmVeSWpSXmKPExsXCtZEjRXf1pe4wg+YuRouX5z+wWqxcfZTJ 4tmhXhYHZo/dNxvYPN7vu8rm8XmTXABzFJdNSmpOZllqkb5dAlfG9cnbWQr6qio6d51jb2Bc k9TFyMkhIWAiceffWlYIW0ziwr31bF2MXBxCAhsZJaac7mUDSQgLOEicnf2cHcQWEVCT2PRq EZDNAVSkIfFuaxaIySwQL3G3kwmkgk3ASOLb+5ksIDavgJbEnwknweIsAioSG+8/BFslKhAh 8WPDEkaIGkGJkzOfgNVzCmhK/G/dBbaJWUBd4s+8S8wQtrzE9rdzmCcw8s9C0jILSdksJGUL GJlXMYrlZuYU56ZnFhga6hUn5qVkFmfrJefnbmIEhyNn5A7GpxPNDzEycXBKNTCyH5eaZ+g4 7xWb+KfZK+ffm2Kskl1mzvPK0SKu2fFO9aw5RafT72Uzie+z/LtO8uQ6/b8HexZ2LVY9MPuf UWTzoUVnN5hYzKrqd/zOKnH2O7+2UGlZgVJu3+dCF+9/pgm3BRzW33DP8pnDdfB63Lrzai9M c+c+3Fmbp2/0+iPzdcXvL+Z1nHJQYinOSDTUYi4qTgQAhKs85PcBAAA= X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD010; 1:lHnaqU7gr83lxYxVtrjHexJaxqrUybogK0nzDpRXUtVd+0q8Jc3vr7A9ctJojLwhnhh926p69IQ2Abqu0bdJjVycC/4QLlKI6r+9t5rD9gUaPFSGBmIaLlbDyMNWh9jUP7VSC9G11jbDA7dbvnpBghlYwfTVjkIl9ey/7MfR5Pf5ALh5fytRsY8hWwVRs2GU3TFhFcUFc9gWTRSteLZyOLaCNK65oeyAC9h7OXsCWmW5/ORrRVxOg6Jk0Y1brrtSMXZTJ1rCSnyiacU1rO+0UL0okfOP4btnJhR8TxVcOOkDP6Aj7JYVEYv8i1WBnhmGyQd11mv6QQdnto8MVLT1Eg== X-Forefront-Antispam-Report: CIP:63.163.107.173; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(2980300002)(438002)(199003)(189002)(64126003)(575784001)(5008740100001)(23676002)(65816999)(586003)(65956001)(230700001)(86362001)(69596002)(50986999)(1220700001)(19580395003)(65806001)(19580405001)(47776003)(76176999)(87936001)(54356999)(87266999)(77096005)(189998001)(106466001)(81156007)(97736004)(33656002)(2950100001)(229853001)(50466002)(92566002)(59896002)(1096002)(80316001)(4001350100001)(83506001)(36756003)(110136002)(4326007)(11100500001)(5001960100002); DIR:OUT; SFP:1101; SCL:1; SRVR:CY1PR0201MB0827; H:milsmgep12.sandisk.com; FPR:; SPF:Pass; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; CY1PR0201MB0827; 2:C2dD4GIZs8Uu7UUOtP9TrfF0Zy9xhOhXYjYLFXChgipV3G0V6xSQxZo8e2jcHWygtbuzvssfkL6gb1wA9hTZzssGPsxi/sbRO/BZ7LmGZmOxYSDdU6EBTX3GDM3co0bvrEfbEH1/rwVsN1g7soMnxg==; 3:VfrmI3Epznp+cvXQm3MQh+UoLaCrTYvYxiP74JaFd1Kc05gUIXJ6ewnUvW3UF4hEP6iT2ZdatSrlje/NFtjB8709bW8vbmrhCrtDQglak5rxUHoT5ssZKygaNWXhka9HQZoZZ7NBiVPwkWgDM7NxnLb269rhUhu+dF8FTZlrIBjLGA6X0fvaBstq6NbfxKA7JDXhP1d89va9vy0AOCbpZCXNdTIVuomGsVqMgMuDJZwjGGmjwPdma65HAUTiFfaNM3fNJaf8tltlqLuvAfBwDA==; 25:nqDX0X6PEXtXQ1iwb4FV+H5+s42kQOf+R2CHtzQDGzI486s8ViVRuJPxhpi+B3UUdGrosH9i2ndyyO7KAhFj+1hjdzmLXrJSuqAry20IQDyV2qk0eIUBJzg+OSHmr0aKbC7gnGpPLvsZAf+nZdZxvRT4yfx4lJ+eqKoDDsJwuDWyypmMVhZGmUhfSZ2iYe61Gpsj1iKuwRGFwJTZ3caeX9gPun3LrxB/eS+NTBgJM6gs03Z25Lmqgo6JtyaUcUscujpz8M5SI07+WIAYrnE7GQ== X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(8251501001); SRVR:CY1PR0201MB0827; X-Microsoft-Exchange-Diagnostics: 1; CY1PR0201MB0827; 20:ybwItPyr3s8ASt2L6LtzENIihQ6lfnaXV4jPg7zKzngJnIcZrtipaLZLAJICR5tFL58EU9/21Wzf0JLSLT0XbLoyv6siXxYsOXO68+auUJnINNZB2TiLoshGwQd5Z93wQ4HmejTmDQtZjQ71fn8lbsfxto5uXjtMq437CqAiHJjtBRR4ymKXlWyYbPdidqgNzziK1S2wmbIs2KwP7DBmf384YPJbobJpvUA//Lz+UK3Lo9tUo7dBegPVEndiiW9pcbqRr8iZ3JrqAgqlKLd183X9cZJ0ZD9VaxtMxATpEXPm43TzlvaYulIxaGr90g45kLpTiKuw3sWglK1jQy2i4QfCJYbtKMh4N2JFtOjZHCKLT0pn7YJtroSrjfQVa25BQKb76tgq5VBtczKY28aGrruf3V8639AQbJ2vZ9N2B8eOSdEMIv1+/7Q/OIIP0lUZ8sqwr72JPjvea/ArWhKEphn6e068+7ykhl5+YWCR+EZo465NIzTd5jvvfoQ+pMko; 4:BwvWshO6sULJl4sXH5gVE4AyAgpTuRAEIaQRUGLLHmJmGL9X9WmDRpStm3mSeq2MrWoRh7RO8zseivn7nai6kwdjOeEU99fVtAoQ1muV/kQ9L+ymZ0qA8WURn5GuOMzu9I6oWO/rfdz4RDtmPcR1FYo2XH+7t2SbYLui5seH62jog6g41xM5CQ1y8ywTD9FlD45WlGC1Y9c/eaR+SSMq7AI51q43gBx1c031WqxnlkgTfCjoskieTZE6f/VdO/64wNkFbFk6x5Tzj5IWYbl8LmBqvI3v6N1hrwgEN/igmDHAK5oQ9qFXgcnJnZJ6SZ/BAFbWVVwQIU2SMbqUVfeLGrqbqzNRVgRrg6cNn0axdTIaXeqsouzlNOnQxOyPyhrA/XXW2e+wzCyHv9MEA7MEkFjL0+Qr/kX3p+sr LpIulYvb/4JHBFoIumKfp4riStS7 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(42932892334569); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(520078)(8121501046)(5005006)(10201501046)(3002001); SRVR:CY1PR0201MB0827; BCL:0; PCL:0; RULEID:; SRVR:CY1PR0201MB0827; X-Forefront-PRVS: 0812095267 X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtDWTFQUjAyMDFNQjA4Mjc7MjM6eHRHTU9NTU5ycldSdjBibGN2NE03bnRk?= =?utf-8?B?alRYc0ZuR3k5cWY2Yk9OVTdMRkFER2pkdVkyK0ExaW0vZ0xka1dpSXBsZ3Q5?= =?utf-8?B?M04vMFIrY2FscDYrMkQ3eHR3UFB0dmMwUndhUzZITHBNODZNc2JvV2pvQW1L?= =?utf-8?B?UDJOS3ZtUXRnN2tnRmV6Skp4dFRCMEVPV2FDV0FLMWViTjdMdUpaOVN5NzNy?= =?utf-8?B?Y3M2TW9oQlg2TEdia1psN2tGQlRCOXVTR0hWdVV6K3h1dVRuR0xERkxqb0RB?= =?utf-8?B?aEhDTXRITGV2ODN5MUJkV3cvYlovT05CV2E5OE1wYVZXNWRjSU1SQWZuZURP?= =?utf-8?B?Q2dvaHFnTlpYUmp0TUtDOGkybm0rUnFuZHdFUXlTaHlod0swaUh1WmUrSmtt?= =?utf-8?B?RnQ1ODlVMWZ2enhJS2tQTy95S1ZUTFBxbm9jZCszVnNsU2FoOTNBV0s0VDBk?= =?utf-8?B?b1hEbk1kbzFtRTh1a3AzRlZiN3VjbEVvV3QwcDV2OGdJbE93bk1qcGhIV2lE?= =?utf-8?B?U1ZkZllsRFl6MS9QVlo5M3dIaTFTVUVEMEVDejM4Tm4rcVZLTDFabWxJOGVF?= =?utf-8?B?UG1aSVJSSGdGK0Q1Q0FvSmlSZGtEUUh5eDJzNm14VVJBNXdUN2drV0ZIeEVR?= =?utf-8?B?KzYyRERSSUYyUmZ1VHNMUkdwRGtubjdWVlh3ZWVMOFlBQ1hpdTZ2NjdXdk90?= =?utf-8?B?WDVSS2svdWM3b1k1RFRNZC85b0I0ZHM0NnBnS2ZObTRGdmk4S28vMzVKem1z?= =?utf-8?B?dy9KRVM2RnkvY2JGQWNzSEs1ZERxd0JaUUEwWmpGclorWWkvT3paU0gzQUd0?= =?utf-8?B?eUJXcXNyZmc0cHR4NStkVDRFM1pseUozSkJGVjJldE5UV1JEUjUzYXNHTjkw?= =?utf-8?B?Q3o4RWNVNU5wU1BrUHJqeUZ1L2VtUSsrNnpzSDNpYlByOUdjR2RFcGg0NEVV?= =?utf-8?B?Z0NucVp6UGxKekx1UUlMY1lXZEgyVlNsbmcwU255S3FmRkxUU3ZqNDQ3RlZ4?= =?utf-8?B?T3VQQ3U3bjhmK3ZLdWszaWdBcVdBMjZ1VVdlOXFmWmV6c2IrREZnWTdPZ3lu?= =?utf-8?B?bjRudHdDN0x2RWZDdVJabmJjOUpkL2lDaHRvUU81ZWNiQWlnTzRPVWRLN2dY?= =?utf-8?B?ak9sU0QwMTdtdFdGMlFJcVJoZTB2M3lNQXo3NXc0eVE5K25oa2E0Nm9BRDRa?= =?utf-8?B?dXV4VEhlT1hWT0Nqd1hXVmdHOXdRY0RmcEQ1d2F0RlVkZm1ub0F0NFB4dnJP?= =?utf-8?B?aUFUVVBydTB6MVY3NW50ZXFjdTQxZ2JTa3plTTRYVDNzdUdBUTV6eVo2OGU0?= =?utf-8?B?dE1uSnRuRWFJQnkvUTcvM2JQOWQ3Ym4wOHRWbjgxbmxsVG9DbEZ5TTdwWE9r?= =?utf-8?B?NFFpZWJsSGM5aksxbWNvUUhOOGx0T3RsakdEamhDczN5RENzc3hXV0c5NUo2?= =?utf-8?B?enRqa1V1dmgzdmhvQ0NBN1QzSFZHVW40WHc1VHVpSDBqRENaS2dtTFpSeTZq?= =?utf-8?B?a0pvN3A5dzNNOGFVTDNldzJYUjVSTFp0bjd3NXg3Rm5JVFFXMnIyUDFVaUE0?= =?utf-8?B?R2FqR2d2bFhFM3V1Vk1PNjVjMVJFcUQwdz09?= X-Microsoft-Exchange-Diagnostics: 1; CY1PR0201MB0827; 5:ENgwMJ3Vd1gl9kXNFVaCxOyCWvKiJSrvW9wfpjnAHQ3XEZ96gLAXsKN2mYxS86nRSfNqwclbAhrTnsQF26lk6TTK/4PVBLvACRB7UI9wSCL9Zbky+L3UX1lPafZl8XnnmBHdcZqLSGdihCLaxC0dQQ==; 24:R13s4fiqEFyjFrr47U7z5PWU8P3o8VRU1Ob7gR2o9+zfCY61FqniLFGodQRNY9GZ4+loZaeAyrHkLzSCJSqbEu/vzNJUN4lAQi/PDrVa1Jw=; 20:dN1NDhgbRhGACwqj0QoxOQ7y4aISHodhuTM2pmiMeWG17ZQC0Yj4DlMcc6PnO0Osu3ot5hzEkCPW9rAplDJ/idzD+UgJdg9gzr3dLpcQpW1AjdZ+AI1WqdsZ+0VFgCoYWMNvlrXh/DOgD6yuCcwHuxaSGW8VAQmjc0nj0G6unQwFWX3IgwI35apuPW7HzcO7LpGmtIw4wwdUNWgg5Olb8f9wVtDMcuztN1rj7OZlamUfoG/Bq5Wfe1kDo9b3CRwh SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: sandisk.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Jan 2016 14:26:51.4059 (UTC) X-MS-Exchange-CrossTenant-Id: fcd9ea9c-ae8c-460c-ab3c-3db42d7ac64d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=fcd9ea9c-ae8c-460c-ab3c-3db42d7ac64d; Ip=[63.163.107.173]; Helo=[milsmgep12.sandisk.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR0201MB0827 Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The Last WQE Reached event is only generated after one or more work requests have been queued on the QP associated with a session. Since session shutdown can start before any work requests have been queued, use a zero-length RDMA write to wait until a QP has been drained. Signed-off-by: Bart Van Assche Cc: Christoph Hellwig Reviewed-by: Christoph Hellwig --- drivers/infiniband/ulp/srpt/ib_srpt.c | 274 +++++++++++++++++----------------- drivers/infiniband/ulp/srpt/ib_srpt.h | 18 ++- 2 files changed, 150 insertions(+), 142 deletions(-) diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 6ec130d..cacb697 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -91,10 +91,11 @@ MODULE_PARM_DESC(srpt_service_guid, " instead of using the node_guid of the first HCA."); static struct ib_client srpt_client; -static void srpt_release_channel(struct srpt_rdma_ch *ch); +static void srpt_free_ch(struct kref *kref); static int srpt_queue_status(struct se_cmd *cmd); static void srpt_recv_done(struct ib_cq *cq, struct ib_wc *wc); static void srpt_send_done(struct ib_cq *cq, struct ib_wc *wc); +static void srpt_zerolength_write_done(struct ib_cq *cq, struct ib_wc *wc); static bool srpt_set_ch_state(struct srpt_rdma_ch *ch, enum rdma_ch_state new) { @@ -170,6 +171,23 @@ static void srpt_srq_event(struct ib_event *event, void *ctx) pr_info("SRQ event %d\n", event->event); } +static const char *get_ch_state_name(enum rdma_ch_state s) +{ + switch (s) { + case CH_CONNECTING: + return "connecting"; + case CH_LIVE: + return "live"; + case CH_DISCONNECTING: + return "disconnecting"; + case CH_DRAINING: + return "draining"; + case CH_DISCONNECTED: + return "disconnected"; + } + return "???"; +} + /** * srpt_qp_event() - QP event callback function. */ @@ -183,11 +201,9 @@ static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch) ib_cm_notify(ch->cm_id, event->event); break; case IB_EVENT_QP_LAST_WQE_REACHED: - if (srpt_set_ch_state(ch, CH_RELEASING)) - srpt_release_channel(ch); - else - pr_debug("%s: state %d - ignored LAST_WQE.\n", - ch->sess_name, ch->state); + pr_debug("%s-%d, state %s: received Last WQE event.\n", + ch->sess_name, ch->qp->qp_num, + get_ch_state_name(ch->state)); break; default: pr_err("received unrecognized IB QP event %d\n", event->event); @@ -789,6 +805,37 @@ out: } /** + * srpt_zerolength_write() - Perform a zero-length RDMA write. + * + * A quote from the InfiniBand specification: C9-88: For an HCA responder + * using Reliable Connection service, for each zero-length RDMA READ or WRITE + * request, the R_Key shall not be validated, even if the request includes + * Immediate data. + */ +static int srpt_zerolength_write(struct srpt_rdma_ch *ch) +{ + struct ib_send_wr wr, *bad_wr; + + memset(&wr, 0, sizeof(wr)); + wr.opcode = IB_WR_RDMA_WRITE; + wr.wr_cqe = &ch->zw_cqe; + wr.send_flags = IB_SEND_SIGNALED; + return ib_post_send(ch->qp, &wr, &bad_wr); +} + +static void srpt_zerolength_write_done(struct ib_cq *cq, struct ib_wc *wc) +{ + struct srpt_rdma_ch *ch = cq->cq_context; + + WARN(wc->status == IB_WC_SUCCESS, "%s-%d: QP not in error state\n", + ch->sess_name, ch->qp->qp_num); + if (srpt_set_ch_state(ch, CH_DISCONNECTED)) + schedule_work(&ch->release_work); + else + WARN_ONCE("%s-%d\n", ch->sess_name, ch->qp->qp_num); +} + +/** * srpt_get_desc_tbl() - Parse the data descriptors of an SRP_CMD request. * @ioctx: Pointer to the I/O context associated with the request. * @srp_cmd: Pointer to the SRP_CMD request data. @@ -1819,111 +1866,102 @@ static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch) } /** - * __srpt_close_ch() - Close an RDMA channel by setting the QP error state. + * srpt_close_ch() - Close an RDMA channel. * - * Reset the QP and make sure all resources associated with the channel will - * be deallocated at an appropriate time. + * Make sure all resources associated with the channel will be deallocated at + * an appropriate time. * - * Note: The caller must hold ch->sport->sdev->spinlock. + * Returns true if and only if the channel state has been modified into + * CH_DRAINING. */ -static void __srpt_close_ch(struct srpt_rdma_ch *ch) +static bool srpt_close_ch(struct srpt_rdma_ch *ch) { - enum rdma_ch_state prev_state; - unsigned long flags; + int ret; - spin_lock_irqsave(&ch->spinlock, flags); - prev_state = ch->state; - switch (prev_state) { - case CH_CONNECTING: - case CH_LIVE: - ch->state = CH_DISCONNECTING; - break; - default: - break; + if (!srpt_set_ch_state(ch, CH_DRAINING)) { + pr_debug("%s-%d: already closed\n", ch->sess_name, + ch->qp->qp_num); + return false; } - spin_unlock_irqrestore(&ch->spinlock, flags); - switch (prev_state) { - case CH_CONNECTING: - ib_send_cm_rej(ch->cm_id, IB_CM_REJ_NO_RESOURCES, NULL, 0, - NULL, 0); - /* fall through */ - case CH_LIVE: - if (ib_send_cm_dreq(ch->cm_id, NULL, 0) < 0) - pr_err("sending CM DREQ failed.\n"); - break; - case CH_DISCONNECTING: - break; - case CH_DRAINING: - case CH_RELEASING: - break; - } -} + kref_get(&ch->kref); -/** - * srpt_close_ch() - Close an RDMA channel. - */ -static void srpt_close_ch(struct srpt_rdma_ch *ch) -{ - struct srpt_device *sdev; + ret = srpt_ch_qp_err(ch); + if (ret < 0) + pr_err("%s-%d: changing queue pair into error state failed: %d\n", + ch->sess_name, ch->qp->qp_num, ret); - sdev = ch->sport->sdev; - spin_lock_irq(&sdev->spinlock); - __srpt_close_ch(ch); - spin_unlock_irq(&sdev->spinlock); -} + pr_debug("%s-%d: queued zerolength write\n", ch->sess_name, + ch->qp->qp_num); + ret = srpt_zerolength_write(ch); + if (ret < 0) { + pr_err("%s-%d: queuing zero-length write failed: %d\n", + ch->sess_name, ch->qp->qp_num, ret); + if (srpt_set_ch_state(ch, CH_DISCONNECTED)) + schedule_work(&ch->release_work); + else + WARN_ON_ONCE(true); + } + + kref_put(&ch->kref, srpt_free_ch); -/** - * srpt_shutdown_session() - Whether or not a session may be shut down. - */ -static int srpt_shutdown_session(struct se_session *se_sess) -{ return true; } -/** - * srpt_drain_channel() - Drain a channel by resetting the IB queue pair. - * @cm_id: Pointer to the CM ID of the channel to be drained. - * - * Note: Must be called from inside srpt_cm_handler to avoid a race between - * accessing sdev->spinlock and the call to kfree(sdev) in srpt_remove_one() - * (the caller of srpt_cm_handler holds the cm_id spinlock; srpt_remove_one() - * waits until all target sessions for the associated IB device have been - * unregistered and target session registration involves a call to - * ib_destroy_cm_id(), which locks the cm_id spinlock and hence waits until - * this function has finished). +/* + * Change the channel state into CH_DISCONNECTING. If a channel has not yet + * reached the connected state, close it. If a channel is in the connected + * state, send a DREQ. If a DREQ has been received, send a DREP. Note: it is + * the responsibility of the caller to ensure that this function is not + * invoked concurrently with the code that accepts a connection. This means + * that this function must either be invoked from inside a CM callback + * function or that it must be invoked with the srpt_port.mutex held. */ -static void srpt_drain_channel(struct srpt_rdma_ch *ch) +static int srpt_disconnect_ch(struct srpt_rdma_ch *ch) { int ret; - bool do_reset = false; - WARN_ON_ONCE(irqs_disabled()); + if (!srpt_set_ch_state(ch, CH_DISCONNECTING)) + return -ENOTCONN; - do_reset = srpt_set_ch_state(ch, CH_DRAINING); + ret = ib_send_cm_dreq(ch->cm_id, NULL, 0); + if (ret < 0) + ret = ib_send_cm_drep(ch->cm_id, NULL, 0); - if (do_reset) { - if (ch->sess) - srpt_shutdown_session(ch->sess); + if (ret < 0 && srpt_close_ch(ch)) + ret = 0; - ret = srpt_ch_qp_err(ch); - if (ret < 0) - pr_err("Setting queue pair in error state" - " failed: %d\n", ret); + return ret; +} + +static void __srpt_close_all_ch(struct srpt_device *sdev) +{ + struct srpt_rdma_ch *ch; + + lockdep_assert_held(&sdev->spinlock); + + list_for_each_entry(ch, &sdev->rch_list, list) { + if (srpt_disconnect_ch(ch) >= 0) + pr_info("Closing channel %s-%d because target %s has been disabled\n", + ch->sess_name, ch->qp->qp_num, + sdev->device->name); + srpt_close_ch(ch); } } /** - * srpt_release_channel() - Release channel resources. - * - * Schedules the actual release because: - * - Calling the ib_destroy_cm_id() call from inside an IB CM callback would - * trigger a deadlock. - * - It is not safe to call TCM transport_* functions from interrupt context. + * srpt_shutdown_session() - Whether or not a session may be shut down. */ -static void srpt_release_channel(struct srpt_rdma_ch *ch) +static int srpt_shutdown_session(struct se_session *se_sess) +{ + return true; +} + +static void srpt_free_ch(struct kref *kref) { - schedule_work(&ch->release_work); + struct srpt_rdma_ch *ch = container_of(kref, struct srpt_rdma_ch, kref); + + kfree(ch); } static void srpt_release_channel_work(struct work_struct *w) @@ -1965,7 +2003,7 @@ static void srpt_release_channel_work(struct work_struct *w) wake_up(&sdev->ch_releaseQ); - kfree(ch); + kref_put(&ch->kref, srpt_free_ch); } static struct srpt_node_acl *__srpt_lookup_acl(struct srpt_port *sport, @@ -2075,17 +2113,10 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, && param->port == ch->sport->port && param->listen_id == ch->sport->sdev->cm_id && ch->cm_id) { - if (ch->state != CH_CONNECTING - && ch->state != CH_LIVE) + if (srpt_disconnect_ch(ch) < 0) continue; - - /* found an existing channel */ - pr_debug("Found existing channel %s" - " cm_id= %p state= %d\n", - ch->sess_name, ch->cm_id, ch->state); - - __srpt_close_ch(ch); - + pr_info("Relogin - closed existing channel %s\n", + ch->sess_name); rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_TERMINATED; } @@ -2116,6 +2147,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, goto reject; } + kref_init(&ch->kref); + ch->zw_cqe.done = srpt_zerolength_write_done; INIT_WORK(&ch->release_work, srpt_release_channel_work); memcpy(ch->i_port_id, req->initiator_port_id, 16); memcpy(ch->t_port_id, req->target_port_id, 16); @@ -2232,7 +2265,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, goto out; release_channel: - srpt_set_ch_state(ch, CH_RELEASING); + srpt_disconnect_ch(ch); transport_deregister_session_configfs(ch->sess); deregister_session: @@ -2282,7 +2315,6 @@ static void srpt_cm_rej_recv(struct srpt_rdma_ch *ch, pr_info("Received CM REJ for ch %s-%d; reason %d; private data %s.\n", ch->sess_name, ch->qp->qp_num, reason, priv ? : "(?)"); kfree(priv); - srpt_drain_channel(ch); } /** @@ -2314,14 +2346,13 @@ static void srpt_cm_timewait_exit(struct srpt_rdma_ch *ch) { pr_info("Received CM TimeWait exit for ch %s-%d.\n", ch->sess_name, ch->qp->qp_num); - srpt_drain_channel(ch); + srpt_close_ch(ch); } static void srpt_cm_rep_error(struct srpt_rdma_ch *ch) { pr_info("Received CM REP error for ch %s-%d.\n", ch->sess_name, ch->qp->qp_num); - srpt_drain_channel(ch); } /** @@ -2329,33 +2360,7 @@ static void srpt_cm_rep_error(struct srpt_rdma_ch *ch) */ static void srpt_cm_dreq_recv(struct srpt_rdma_ch *ch) { - unsigned long flags; - bool send_drep = false; - - pr_debug("ch %s-%d state %d\n", ch->sess_name, ch->qp->qp_num, - ch->state); - - spin_lock_irqsave(&ch->spinlock, flags); - switch (ch->state) { - case CH_CONNECTING: - case CH_LIVE: - send_drep = true; - ch->state = CH_DISCONNECTING; - break; - case CH_DISCONNECTING: - case CH_DRAINING: - case CH_RELEASING: - WARN(true, "unexpected channel state %d\n", ch->state); - break; - } - spin_unlock_irqrestore(&ch->spinlock, flags); - - if (send_drep) { - if (ib_send_cm_drep(ch->cm_id, NULL, 0) < 0) - pr_err("Sending IB DREP failed.\n"); - pr_info("Received DREQ and sent DREP for session %s.\n", - ch->sess_name); - } + srpt_disconnect_ch(ch); } /** @@ -2364,7 +2369,7 @@ static void srpt_cm_dreq_recv(struct srpt_rdma_ch *ch) static void srpt_cm_drep_recv(struct srpt_rdma_ch *ch) { pr_info("Received InfiniBand DREP message for cm_id %p.\n", ch->cm_id); - srpt_drain_channel(ch); + srpt_close_ch(ch); } /** @@ -2539,7 +2544,7 @@ static int srpt_write_pending(struct se_cmd *se_cmd) break; case CH_DISCONNECTING: case CH_DRAINING: - case CH_RELEASING: + case CH_DISCONNECTED: pr_debug("cmd with tag %lld: channel disconnecting\n", ioctx->cmd.tag); srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN); @@ -2696,16 +2701,16 @@ static int srpt_ch_list_empty(struct srpt_device *sdev) */ static int srpt_release_sdev(struct srpt_device *sdev) { - struct srpt_rdma_ch *ch, *tmp_ch; - int res; + int i, res; WARN_ON_ONCE(irqs_disabled()); BUG_ON(!sdev); spin_lock_irq(&sdev->spinlock); - list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) - __srpt_close_ch(ch); + for (i = 0; i < ARRAY_SIZE(sdev->port); i++) + sdev->port[i].enabled = false; + __srpt_close_all_ch(sdev); spin_unlock_irq(&sdev->spinlock); res = wait_event_interruptible(sdev->ch_releaseQ, @@ -3007,9 +3012,10 @@ static void srpt_close_session(struct se_session *se_sess) BUG_ON(ch->release_done); ch->release_done = &release_done; wait = !list_empty(&ch->list); - __srpt_close_ch(ch); spin_unlock_irq(&sdev->spinlock); + srpt_disconnect_ch(ch); + if (!wait) return; diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h index d0de468..17058ef 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.h +++ b/drivers/infiniband/ulp/srpt/ib_srpt.h @@ -218,20 +218,20 @@ struct srpt_send_ioctx { /** * enum rdma_ch_state - SRP channel state. - * @CH_CONNECTING: QP is in RTR state; waiting for RTU. - * @CH_LIVE: QP is in RTS state. - * @CH_DISCONNECTING: DREQ has been received; waiting for DREP - * or DREQ has been send and waiting for DREP - * or . - * @CH_DRAINING: QP is in ERR state; waiting for last WQE event. - * @CH_RELEASING: Last WQE event has been received; releasing resources. + * @CH_CONNECTING: QP is in RTR state; waiting for RTU. + * @CH_LIVE: QP is in RTS state. + * @CH_DISCONNECTING: DREQ has been sent and waiting for DREP or DREQ has + * been received. + * @CH_DRAINING: DREP has been received or waiting for DREP timed out + * and last work request has been queued. + * @CH_DISCONNECTED: Last completion has been received. */ enum rdma_ch_state { CH_CONNECTING, CH_LIVE, CH_DISCONNECTING, CH_DRAINING, - CH_RELEASING + CH_DISCONNECTED, }; /** @@ -268,6 +268,8 @@ struct srpt_rdma_ch { struct ib_cm_id *cm_id; struct ib_qp *qp; struct ib_cq *cq; + struct ib_cqe zw_cqe; + struct kref kref; int rq_size; u32 rsp_size; atomic_t sq_wr_avail;