From patchwork Thu Nov 9 03:17:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Madhani, Himanshu" X-Patchwork-Id: 10050043 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 6F967601EB for ; Thu, 9 Nov 2017 03:18:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6425D2A973 for ; Thu, 9 Nov 2017 03:18:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5900F2A972; Thu, 9 Nov 2017 03:18:09 +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.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_HI 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 B84692A96F for ; Thu, 9 Nov 2017 03:18:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751767AbdKIDSH (ORCPT ); Wed, 8 Nov 2017 22:18:07 -0500 Received: from mail-dm3nam03on0059.outbound.protection.outlook.com ([104.47.41.59]:51648 "EHLO NAM03-DM3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751550AbdKIDSE (ORCPT ); Wed, 8 Nov 2017 22:18:04 -0500 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=hvlP7lW+IB2sDJIH2rJ9ReT+xjgI1cHYzHUtyWbpY8k=; b=L1qYGgRrjrL+o/Gqt34S3ZTbJ7zUZ6eKCwHPwrDWxptYt9I8+RRhWo1QRYOfbfQBJ9LsgpmJ+/S3WH5f7S3YXBllBhU88CkRQqRWEOYrD706nNPYjDpVHMp520zWlL0dBqFBxRIZxKyJxZecQNSzSqo3/ARqDYIO6Cuvna//mLs= Received: from BY2PR07CA0031.namprd07.prod.outlook.com (2a01:111:e400:7bff::26) by MWHPR0701MB3820.namprd07.prod.outlook.com (2603:10b6:301:7f::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.197.13; Thu, 9 Nov 2017 03:17:59 +0000 Received: from BY2FFO11FD043.protection.gbl (2a01:111:f400:7c0c::180) by BY2PR07CA0031.outlook.office365.com (2a01:111:e400:7bff::26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.197.13 via Frontend Transport; Thu, 9 Nov 2017 03:17:59 +0000 Authentication-Results: spf=none (sender IP is 50.232.66.26) smtp.mailfrom=cavium.com; HansenPartnership.com; dkim=none (message not signed) header.d=none;HansenPartnership.com; 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 BY2FFO11FD043.mail.protection.outlook.com (10.1.14.228) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.20.178.5 via Frontend Transport; Thu, 9 Nov 2017 03:17:58 +0000 Received: from dut1171.mv.qlogic.com (172.29.51.171) by CAEXCH02.caveonetworks.com (10.17.4.29) with Microsoft SMTP Server id 14.2.347.0; Wed, 8 Nov 2017 19:17:55 -0800 Received: from dut1171.mv.qlogic.com (localhost [127.0.0.1]) by dut1171.mv.qlogic.com (8.14.7/8.14.7) with ESMTP id vA93HtPd010312; Wed, 8 Nov 2017 19:17:55 -0800 Received: (from root@localhost) by dut1171.mv.qlogic.com (8.14.7/8.14.7/Submit) id vA93Ht29010311; Wed, 8 Nov 2017 19:17:55 -0800 From: Himanshu Madhani To: , , , , , CC: , Subject: [PATCH v2 1/4] qla2xxx_nvmet: Add files for FC-NVMe Target support Date: Wed, 8 Nov 2017 19:17:51 -0800 Message-ID: <20171109031754.10270-2-himanshu.madhani@cavium.com> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20171109031754.10270-1-himanshu.madhani@cavium.com> References: <20171109031754.10270-1-himanshu.madhani@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)(376002)(346002)(2980300002)(428002)(199003)(189002)(50226002)(8936002)(101416001)(48376002)(33646002)(80596001)(50466002)(4326008)(54906003)(5660300001)(72206003)(2906002)(2950100002)(50986999)(2201001)(16586007)(47776003)(5003940100001)(316002)(76176999)(42186006)(106466001)(6666003)(105586002)(81166006)(81156014)(189998001)(356003)(69596002)(86362001)(8676002)(305945005)(478600001)(110136005)(1076002)(36756003)(87636003)(2101003); DIR:OUT; SFP:1101; SCL:1; SRVR:MWHPR0701MB3820; H:CAEXCH02.caveonetworks.com; FPR:; SPF:None; PTR:50-232-66-26-static.hfc.comcastbusiness.net; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD043; 1:RdIeEDnqVi9ue8Gtp14vuPstaTyM5VJOWQEMMENcpCG5vlOLztiDswbov2WhqYnsFcBLlzM82o6D7pLMSXTktCIIAwIrhjKpaH4+UCMi/X1xTvOSRh3yAKNwqSlKgs/C X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 34e4f9b4-8d90-4bba-d776-08d527207a97 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603199); SRVR:MWHPR0701MB3820; X-Microsoft-Exchange-Diagnostics: 1; MWHPR0701MB3820; 3:/PPoTKoz24Fs1jw4dUzqeF5lDPXns4ap2dThjhcirhNSRr6sFjpxb0akcpHRaYihelI+W/+MrWfbDMpzi3kmErXfaN+I7wb9Qt3Jm+mWTcXGtvG2weAQ/juaE1GfhbnaF4KinyIdRTm02SiaNDOfsprZAHAn0mGoNRBBRJKvgRlRT8r2eRfSSwzF1Gpwjf9xufN4WcBNpc1TvyOBQjVDKtCCwU+FIdBrlOZBPiVTtZbFLPU69WcZ6tTEg0lvTxIw/YFOH6rSKdLgV9xVjkttgtij0V6iyhxl2YcK69dvPvRvznz745VQOpefg/nOFmJ6ogAJ1qaeg2ZVQORn1ujkIlRBRSbOM1BVKA2YaEAFymE=; 25:bLllZVy5xYlDt8t9NB7NtEDoyADBAnpT5j3k2BdWM2BRxa0MDU4jxWGKGOjhgrdY1XXAFhM8g5O9V9/FQfYrqWRzcgQTx3N9Koaewu1bEj2ijDo7M1hCa83O4q1NyQMgUIFz4ykVuU+sC9yXRc+e2NCBHNgfM2etTPKViXycEhXdVS/iznThhaz6YMuqKQdc9nx3Q243Jo9/wx1+CoKRP3ZqR8mnWYu92gx6ybRyVJdIZo6w2yid5YtvdAeFN5ss4W/2GozLoUn0ImWH3ewk6cVhY1Ze0ePnn2bA4Ao18Vv8pprkr84c1W5fndaNb7tkPFN8pgC4ODXA9V+0NDDfKw== X-MS-TrafficTypeDiagnostic: MWHPR0701MB3820: X-Microsoft-Exchange-Diagnostics: 1; MWHPR0701MB3820; 31:cdlyMwBjVt4dHSw1DMBTx2j+vEieAJW7yicfLSbZ3XdG520BH1tIBo8FZ/ehF+kbd+J0epFBH+B+DESLLL0hY/OvZdEQ9FjXOngRpIMEK/V2ZVXPkeCNETP9b+AyEO9lukf/o//Qu/GKTBMTms8xh/JS+1zkxcVi+gkRPirZZhgrCF0zgkAb9kfooZuPCWDoUQBYRLdqtJHgbYe7oy318OCDa2V8ytVV7mmVKbnLrQA=; 20:xBVadavMXf80bCUMBRcOjVaFS/KOdf0Ig9hoHxn1p+HRXrN9T8TGXSSwiy88qZjyu6EOVy1TDMmHS53L8isFgmmjBgZjPfJrfD9vHl3h2kQnCbVa/iowGmLTHMEi/mBka2++hS3NZbSX2NQ46ZjKr6JjddDG05c2aoEFHJHvPdrRSBKBeWeD5gswrtZqOi27EOdro9/Cb2zmuR9AK37UMOdeT/Fa7dGvttsTC3kslU9P28eRMjKjazQmBKEcFVl3XjLf9uYmTaKP3y8yNCLRYl+yvTRPmqkZ+aar5sT/jXw4SwQFIN7/sf/eOZLY6T9dCpLD4kHJCcH+39i5Ao4rVSqZwnFO4Mv57/VPIca44yDc0N+z0zgVrPtDHPsj2H9YwL3rjTOPHXUG7o/bhC1YwwFeP+iu3gtPASpSqIaVls7rqD+B9aIMXtzTysbWfKKpGmdiI2xkcuv0XmlafKwpPpj2apSAA1ntQ8dx5erucBv0bzuPfco0HLeRVQAB+tbj X-Exchange-Antispam-Report-Test: UriScan:; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(8121501046)(5005006)(93006095)(93001095)(10201501046)(100000703101)(100105400095)(3231021)(3002001)(6041248)(20161123564025)(20161123562025)(20161123558100)(20161123560025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123555025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:MWHPR0701MB3820; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:MWHPR0701MB3820; X-Microsoft-Exchange-Diagnostics: 1; MWHPR0701MB3820; 4:regnO0DCplUrQN7GqmIlJol2JEexH5SHyv6Lgd/SKCrWIW2nSZvU6Be51L9OQ5/OeR5TNcvKV3tBHYIjIf0m9NLg8ZQboWrkGSif8KorNT9nYpCowV9ukI/WVEEp1NasXYZGvWRN/m8pdVq1i8H2nbUuUi1EQ2B52aunT7KNeGEEuGH8AjWilWEZ2Jk6FJnT+2WQueJMDEsTFhcRt7Hre1woQ41OFLW7075GRYALZuUUfsdxWeR2eAU81F/HqRlFiA8f2v+jT9OmIj7Cbj3YqQ== X-Forefront-PRVS: 0486A0CB86 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; MWHPR0701MB3820; 23:ESmrlrEKsfnfehfiMV8UF2p6V3jXgdpFkNb7JTS?= =?us-ascii?Q?3UVfCAoX8Ajjwli1oC6+9fG7kD37RirFAJwqqbuCwaNjB+gWEQW+rffijZO7?= =?us-ascii?Q?ySUTBYwozXH+XMgqzSO2FlhcttMYM7Vn/PJPqJSXquvONTr0EkK4GR4zIQ8d?= =?us-ascii?Q?h+somv5Btmdx34u1tOp/8fBZN3h5gsOfQFoo546SvoOoFD5snmuiWkLMoKPz?= =?us-ascii?Q?AU0en2WjbuG7sxH7ysOco27qiKjm12DkBWa+7GONO387de0ee3fafKr3IIYw?= =?us-ascii?Q?vcUu9UwwRZmSNccAvkuPCnaE7DqwE6SeRHOE6AVVp/nrJLCkMKLDk0MCxegn?= =?us-ascii?Q?qqSo6OIGW/xss1j8l9Wy4JoVcOAEgOoTG+8CdehEcihIDGm4esN/LduRJc5O?= =?us-ascii?Q?oH28FSy58F9tu+fEjBk7FFQGVzQN1FTme7U9cfl5ajk8XZ2xdCB1RHx9zZW2?= =?us-ascii?Q?UnnbPIagCDvhZeXBEh8YQebD7BUkw6fuKdsnRKT9n6fNE7gf7zP4K6dc2hJk?= =?us-ascii?Q?HMEPmBKwPpy6Wk92W0TtBzyVaaeQ08EsZUJgyYWC9tun4jTY13WCP5H9IWv9?= =?us-ascii?Q?TtIW0ANErwmE371BeVuHL14nNjWemvL/GNcjGUHGvfYVdSHjwVXvSCgcra2u?= =?us-ascii?Q?80Y4n+V1ONGxWmPDb04xR+H8OcqXLyPQrNatG1Z3w/TfY/O3rzbVr1Uu+y/i?= =?us-ascii?Q?ndgWSWUgLfI1z5bhYO+TThlBk+BKXIkhWKPsIbleDgi+UDso1JJg98zJXIXM?= =?us-ascii?Q?Vseeae57ZtSLVPgF8idYCalLEFDwcz9j3+n3Wmr95AI2vD36QPdzQOiExDLP?= =?us-ascii?Q?0wiYJ6kQO7Q2wE8nCh1w/4JHLJXyQPseurQYUsweUHiHGr4+2TFw3dEvR0Fl?= =?us-ascii?Q?f8s8riYerV6HAN80QTkyDabq1THAXVIsEt6Z89SP/6XdwaJrhFN0ioljIgs7?= =?us-ascii?Q?6KfPbQPJ3u0Dgzi5ByOrzPMRKnkSHXH+qgYmJpXku3ULKOq+jMQHPg89fYZ1?= =?us-ascii?Q?lSGrtakJF0vwqjCSj1heEUep+L2ZkNJIdLRZjAj2uWuE3Z9jzx28RiHYdhpd?= =?us-ascii?Q?nQaWnB4SFgeVNX3G6Ze+FsWHT0UE2?= X-Microsoft-Exchange-Diagnostics: 1; MWHPR0701MB3820; 6:q6xRhOKVFtk9/5ym7/ApisHtlBdaAf7umRil7pizuqJdkmTKNhCPflzUNeuIJo3IlO6x+V2TPEmj/umQgWvH0TV/+QbMugqFKiYMXy5EQIEXm2MU4GOAutsLEROKiDaTBnotafRWB2GooeNTMx+8IA6/ZDItvG0iXS3Iv78/r8v758gJYPPrdW1apTr0pIjW7NxNlBCCmmYdeOhPbTkjoY1MN8+q3Bqt8nj3tzO8qTWXqzrTotPRh9FqrdjKKYq435nHA5mP8G5YTamJT8byJhrgR8YeNABiV16hg+2l92vwlY05FKJ9udaG9ePs6EI5+5Amb98fHvwvrib5iM7gH+23LTmT0D68tmBZBzVCLIA=; 5:9CUX7XazwxeZAbv6w8I9HV+fDJwt5OgIQBH0Ev6PeacHjbpwQQFhFCp1aEFNwAibjNOrDRUYdJBjPzE8SqIJt8Ta8rQQE0g7qXQjepRsVQWaIm8LtuaDI4g9rxmhNsq3ng+lLx9bNYc0WTNUOtksMxRA3dvCHwA/GY3bMpYYuGM=; 24:6rH1vrHCEvgCX1lJhGACCSzAWuOePoMWN5+h3VVR4OOC3gJw22fFmy58t1RyVmGg2e5qcdd6flo4CC0MvD8VeGfxupR9mTV3hna0i0LoQCA=; 7:HMjK1rjAJnWDp4R2INkBzvqbU1N+BLToj9mYiS1cQyENCe2/sDg9ZUNfaRsVwNcyvqY7+/WhE1OdQ2yxCdgmvao6/GLAoCFXVzSfHcQOFfdynhsGRULpzl4vrugFmTprMGjYpGAWiv1T6seEbY4+E55WP08+La+gILuspxFnvvQX+bEs4q5u9WTNVMqDGpPu+3LPTESy37mP9GyrK8yKqUgvssKzkuTGcRDk00uWxbkvjQpLs3oLObNdQaPI6EQS SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Nov 2017 03:17:58.9973 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 34e4f9b4-8d90-4bba-d776-08d527207a97 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: MWHPR0701MB3820 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Anil Gurumurthy Signed-off-by: Anil Gurumurthy Signed-off-by: Giridhar Malavali Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_nvmet.c | 783 +++++++++++++++++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_nvmet.h | 130 +++++++ 2 files changed, 913 insertions(+) create mode 100644 drivers/scsi/qla2xxx/qla_nvmet.c create mode 100644 drivers/scsi/qla2xxx/qla_nvmet.h diff --git a/drivers/scsi/qla2xxx/qla_nvmet.c b/drivers/scsi/qla2xxx/qla_nvmet.c new file mode 100644 index 000000000000..ed486a2f899f --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_nvmet.c @@ -0,0 +1,783 @@ + +/* + * QLogic Fibre Channel HBA Driver + * Copyright (c) 2003-2017 QLogic Corporation + * + * See LICENSE.qla2xxx for copyright and licensing details. + */ +#include +#include +#include +#include + +#include "qla_nvme.h" +#include "qla_nvmet.h" + +#if IS_ENABLED(CONFIG_NVME_TARGET_FC) +static void qla_nvmet_send_resp_ctio(struct qla_qpair *qpair, + struct qla_nvmet_cmd *cmd, struct nvmefc_tgt_fcp_req *rsp); +static void qla_nvmet_send_abts_ctio(struct scsi_qla_host *vha, + struct abts_recv_from_24xx *abts, bool flag); + +/* + * qla_nvmet_targetport_delete - + * Invoked by the nvmet to indicate that the target port has + * been deleted + */ +static void +qla_nvmet_targetport_delete(struct nvmet_fc_target_port *targetport) +{ + struct qla_nvmet_tgtport *tport = targetport->private; + + complete(&tport->tport_del); +} +#endif + +#if IS_ENABLED(CONFIG_NVME_TARGET_FC) +/* + * qlt_nvmet_ls_done - + * Invoked by the firmware interface to indicate the completion + * of an LS cmd + * Free all associated resources of the LS cmd + */ +static void qlt_nvmet_ls_done(void *ptr, int res) +{ + struct srb *sp = ptr; + struct srb_iocb *nvme = &sp->u.iocb_cmd; + struct nvmefc_tgt_ls_req *rsp = nvme->u.nvme.desc; + struct qla_nvmet_cmd *tgt_cmd = nvme->u.nvme.cmd; + + ql_log(ql_log_info, sp->vha, 0x11000, + "Done with NVME LS4 req\n"); + + ql_log(ql_log_info, sp->vha, 0x11001, + "sp: %p vha: %p, rsp: %p, cmd: %p\n", + sp, sp->vha, nvme->u.nvme.desc, nvme->u.nvme.cmd); + + rsp->done(rsp); + /* Free tgt_cmd */ + kfree(tgt_cmd->buf); + kfree(tgt_cmd); + qla2x00_rel_sp(sp); +} + +/* + * qla_nvmet_ls_rsp - + * Invoked by the nvme-t to complete the LS req. + * Prepare and send a response CTIO to the firmware. + */ +static int +qla_nvmet_ls_rsp(struct nvmet_fc_target_port *tgtport, + struct nvmefc_tgt_ls_req *rsp) +{ + struct qla_nvmet_cmd *tgt_cmd = + container_of(rsp, struct qla_nvmet_cmd, cmd.ls_req); + struct scsi_qla_host *vha = tgt_cmd->vha; + struct srb_iocb *nvme; + int rval = QLA_FUNCTION_FAILED; + srb_t *sp; + + ql_log(ql_log_info, vha, 0x11002, + "Dumping the NVMET-LS response buffer\n"); + ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2075, + (uint8_t *)rsp->rspbuf, rsp->rsplen); + + /* Alloc SRB structure */ + sp = qla2x00_get_sp(vha, NULL, GFP_ATOMIC); + if (!sp) { + ql_log(ql_log_info, vha, 0x11003, "Failed to allocate SRB\n"); + return -ENOMEM; + } + + sp->type = SRB_NVMET_LS; + sp->done = qlt_nvmet_ls_done; + sp->vha = vha; + sp->fcport = tgt_cmd->fcport; + + nvme = &sp->u.iocb_cmd; + nvme->u.nvme.rsp_dma = rsp->rspdma; + nvme->u.nvme.rsp_len = rsp->rsplen; + nvme->u.nvme.exchange_address = tgt_cmd->atio.u.pt_ls4.exchange_address; + nvme->u.nvme.nport_handle = tgt_cmd->atio.u.pt_ls4.nport_handle; + nvme->u.nvme.vp_index = tgt_cmd->atio.u.pt_ls4.vp_index; + + nvme->u.nvme.cmd = tgt_cmd; /* To be freed */ + nvme->u.nvme.desc = rsp; /* Call back to nvmet */ + + rval = qla2x00_start_sp(sp); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x11004, + "qla2x00_start_sp failed = %d\n", rval); + return rval; + } + + return 0; +} + +/* + * qla_nvmet_fcp_op - + * Invoked by the nvme-t to complete the IO. + * Prepare and send a response CTIO to the firmware. + */ +static int +qla_nvmet_fcp_op(struct nvmet_fc_target_port *tgtport, + struct nvmefc_tgt_fcp_req *rsp) +{ + struct qla_nvmet_cmd *tgt_cmd = + container_of(rsp, struct qla_nvmet_cmd, cmd.fcp_req); + struct scsi_qla_host *vha = tgt_cmd->vha; + + /* Prepare and send CTIO 82h */ + qla_nvmet_send_resp_ctio(vha->qpair, tgt_cmd, rsp); + + return 0; +} +/* + * qla_nvmet_fcp_abort_done + * free up the used resources + */ +static void qla_nvmet_fcp_abort_done(void *ptr, int res) +{ + srb_t *sp = ptr; + + qla2x00_rel_sp(sp); +} + +/* + * qla_nvmet_fcp_abort - + * Invoked by the nvme-t to abort an IO + * Send an abort to the firmware + */ +static void +qla_nvmet_fcp_abort(struct nvmet_fc_target_port *tgtport, + struct nvmefc_tgt_fcp_req *req) +{ + struct qla_nvmet_cmd *tgt_cmd = + container_of(req, struct qla_nvmet_cmd, cmd.fcp_req); + struct scsi_qla_host *vha = tgt_cmd->vha; + struct qla_hw_data *ha = vha->hw; + srb_t *sp; + + /* Alloc SRB structure */ + sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL); + if (!sp) { + ql_log(ql_log_info, vha, 0x11005, "Failed to allocate SRB\n"); + return; + } + + sp->type = SRB_NVMET_SEND_ABTS; + sp->done = qla_nvmet_fcp_abort_done; + sp->vha = vha; + sp->fcport = tgt_cmd->fcport; + + ha->isp_ops->abort_command(sp); + +} + +/* + * qla_nvmet_fcp_req_release - + * Delete the cmd from the list and free the cmd + */ + +static void +qla_nvmet_fcp_req_release(struct nvmet_fc_target_port *tgtport, + struct nvmefc_tgt_fcp_req *rsp) +{ + struct qla_nvmet_cmd *tgt_cmd = + container_of(rsp, struct qla_nvmet_cmd, cmd.fcp_req); + scsi_qla_host_t *vha = tgt_cmd->vha; + unsigned long flags; + + spin_lock_irqsave(&vha->cmd_list_lock, flags); + list_del(&tgt_cmd->cmd_list); + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); + + kfree(tgt_cmd); +} + +static struct nvmet_fc_target_template qla_nvmet_fc_transport = { + .targetport_delete = qla_nvmet_targetport_delete, + .xmt_ls_rsp = qla_nvmet_ls_rsp, + .fcp_op = qla_nvmet_fcp_op, + .fcp_abort = qla_nvmet_fcp_abort, + .fcp_req_release = qla_nvmet_fcp_req_release, + .max_hw_queues = 8, + .max_sgl_segments = 128, + .max_dif_sgl_segments = 64, + .dma_boundary = 0xFFFFFFFF, + .target_features = NVMET_FCTGTFEAT_READDATA_RSP | + NVMET_FCTGTFEAT_CMD_IN_ISR | + NVMET_FCTGTFEAT_OPDONE_IN_ISR, + .target_priv_sz = sizeof(struct nvme_private), +}; +#endif +/* + * qla_nvmet_create_targetport - + * Create a targetport. Registers the template with the nvme-t + * layer + */ +int qla_nvmet_create_targetport(struct scsi_qla_host *vha) +{ +#if IS_ENABLED(CONFIG_NVME_TARGET_FC) + struct nvmet_fc_port_info pinfo; + struct qla_nvmet_tgtport *tport; + int error = 0; + + ql_dbg(ql_dbg_nvme, vha, 0xe081, + "Creating target port for :%p\n", vha); + + memset(&pinfo, 0, (sizeof(struct nvmet_fc_port_info))); + pinfo.node_name = wwn_to_u64(vha->node_name); + pinfo.port_name = wwn_to_u64(vha->port_name); + pinfo.port_id = vha->d_id.b24; + + error = nvmet_fc_register_targetport(&pinfo, + &qla_nvmet_fc_transport, &vha->hw->pdev->dev, + &vha->targetport); + + if (error) { + ql_dbg(ql_dbg_nvme, vha, 0xe082, + "Cannot register NVME transport:%d\n", error); + return error; + } + tport = (struct qla_nvmet_tgtport *)vha->targetport->private; + tport->vha = vha; + ql_dbg(ql_dbg_nvme, vha, 0xe082, + " Registered NVME transport:%p WWPN:%llx\n", + tport, pinfo.port_name); +#endif + return 0; +} + +/* + * qla_nvmet_delete - + * Delete a targetport. + */ +int qla_nvmet_delete(struct scsi_qla_host *vha) +{ +#if IS_ENABLED(CONFIG_NVME_TARGET_FC) + struct qla_nvmet_tgtport *tport; + + if (!vha->flags.nvmet_enabled) + return 0; + if (vha->targetport) { + tport = (struct qla_nvmet_tgtport *)vha->targetport->private; + + ql_dbg(ql_dbg_nvme, vha, 0xe083, + "Deleting target port :%p\n", tport); + init_completion(&tport->tport_del); + nvmet_fc_unregister_targetport(vha->targetport); + wait_for_completion_timeout(&tport->tport_del, 5); + + nvmet_release_sessions(vha); + } +#endif + return 0; +} + +/* + * qla_nvmet_handle_ls - + * Handle a link service request from the initiator. + * Get the LS payload from the ATIO queue, invoke + * nvmet_fc_rcv_ls_req to pass the LS req to nvmet. + */ +int qla_nvmet_handle_ls(struct scsi_qla_host *vha, + struct pt_ls4_rx_unsol *pt_ls4, void *buf) +{ +#if IS_ENABLED(CONFIG_NVME_TARGET_FC) + struct qla_nvmet_cmd *tgt_cmd; + uint32_t size; + int ret; + uint32_t look_up_sid; + fc_port_t *sess = NULL; + + look_up_sid = pt_ls4->s_id[2] << 16 | + pt_ls4->s_id[1] << 8 | pt_ls4->s_id[0]; + + ql_log(ql_log_info, vha, 0x11005, + "%s - Look UP sid: %#x\n", __func__, look_up_sid); + + sess = qla_nvmet_find_sess_by_s_id(vha, look_up_sid); + if (unlikely(!sess)) + WARN_ON(1); + + size = cpu_to_le16(pt_ls4->desc_len) + 8; + + tgt_cmd = kzalloc(sizeof(struct qla_nvmet_cmd), GFP_ATOMIC); + if (tgt_cmd == NULL) { + ql_dbg(ql_dbg_nvme, vha, 0xe084, + "Memory allocation failed\n"); + return -ENOMEM; + } + tgt_cmd->vha = vha; + tgt_cmd->ox_id = pt_ls4->ox_id; + tgt_cmd->buf = buf; + /* Store the received nphdl, rx_exh_addr etc */ + memcpy(&tgt_cmd->atio.u.pt_ls4, pt_ls4, sizeof(struct pt_ls4_rx_unsol)); + tgt_cmd->fcport = sess; + + ql_log(ql_log_info, vha, 0x11006, + "Dumping the PURLS-ATIO request\n"); + ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2075, + (uint8_t *)pt_ls4, sizeof(struct pt_ls4_rx_unsol)); + + ql_log(ql_log_info, vha, 0x11007, + "Sending LS to nvmet buf: %p, len: %#x\n", buf, size); + + ret = nvmet_fc_rcv_ls_req(vha->targetport, + &tgt_cmd->cmd.ls_req, buf, size); + + if (ret == 0) { + ql_log(ql_log_info, vha, 0x11008, + "LS req handled successfully\n"); + return 0; + } + ql_log(ql_log_warn, vha, 0x11009, + "LS req failed\n"); + + return ret; +#else + return 0; +#endif +} + +/* + * qla_nvmet_process_cmd - + * Handle NVME cmd request from the initiator. + * Get the NVME payload from the ATIO queue, invoke + * nvmet_fc_rcv_ls_req to pass the LS req to nvmet. + * On a failure send an abts to the initiator? + */ +int qla_nvmet_process_cmd(struct scsi_qla_host *vha, + struct qla_nvmet_cmd *tgt_cmd) +{ +#if IS_ENABLED(CONFIG_NVME_TARGET_FC) + int ret; + struct atio7_nvme_cmnd *nvme_cmd; + + nvme_cmd = (struct atio7_nvme_cmnd *)&tgt_cmd->nvme_cmd_iu; + + ret = nvmet_fc_rcv_fcp_req(vha->targetport, &tgt_cmd->cmd.fcp_req, + nvme_cmd, tgt_cmd->cmd_len); + if (ret != 0) { + ql_log(ql_log_warn, vha, 0x1100a, + "%s-%d - Failed (ret: %#x) to process NVME command\n", + __func__, __LINE__, ret); + /* Send ABTS to initator ? */ + } +#endif + return 0; +} + +/* + * qla_nvmet_handle_abts + * Handle an abort from the initiator + * Invoke nvmet_fc_rcv_fcp_abort to pass the abts to the nvmet + */ +int qla_nvmet_handle_abts(struct scsi_qla_host *vha, + struct abts_recv_from_24xx *abts) +{ +#if IS_ENABLED(CONFIG_NVME_TARGET_FC) + uint16_t ox_id = cpu_to_be16(abts->fcp_hdr_le.ox_id); + unsigned long flags; + struct qla_nvmet_cmd *cmd = NULL; + + /* Retrieve the cmd from cmd list */ + spin_lock_irqsave(&vha->cmd_list_lock, flags); + list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { + if (cmd->ox_id == ox_id) + break; /* Found the cmd */ + } + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); + if (!cmd) { + ql_log(ql_log_warn, vha, 0x1100b, + "%s-%d - Command not found\n", __func__, __LINE__); + /* Send a RJT */ + qla_nvmet_send_abts_ctio(vha, abts, 0); + return 0; + } + + nvmet_fc_rcv_fcp_abort(vha->targetport, &cmd->cmd.fcp_req); + /* Send an ACC */ + qla_nvmet_send_abts_ctio(vha, abts, 1); +#endif + return 0; +} + +#if IS_ENABLED(CONFIG_NVME_TARGET_FC) +/* + * qla_nvmet_abts_done + * Complete the cmd back to the nvme-t and + * free up the used resources + */ +static void qla_nvmet_abts_done(void *ptr, int res) +{ + srb_t *sp = ptr; + + qla2x00_rel_sp(sp); +} +/* + * qla_nvmet_fcp_done + * Complete the cmd back to the nvme-t and + * free up the used resources + */ +static void qla_nvmet_fcp_done(void *ptr, int res) +{ + srb_t *sp = ptr; + struct nvmefc_tgt_fcp_req *rsp; + + rsp = sp->u.iocb_cmd.u.nvme.desc; + + if (res) { + rsp->fcp_error = NVME_SC_SUCCESS; + if (rsp->op == NVMET_FCOP_RSP) + rsp->transferred_length = 0; + else + rsp->transferred_length = rsp->transfer_length; + } else { + rsp->fcp_error = NVME_SC_DATA_XFER_ERROR; + rsp->transferred_length = 0; + } + rsp->done(rsp); + qla2x00_rel_sp(sp); +} + +/* + * qla_nvmet_send_resp_ctio + * Send the response CTIO to the firmware + */ +static void qla_nvmet_send_resp_ctio(struct qla_qpair *qpair, + struct qla_nvmet_cmd *cmd, struct nvmefc_tgt_fcp_req *rsp_buf) +{ + struct atio_from_isp *atio = &cmd->atio; + struct ctio_nvme_to_27xx *ctio; + struct scsi_qla_host *vha = cmd->vha; + struct qla_hw_data *ha = vha->hw; + struct fcp_hdr *fchdr = &atio->u.nvme_isp27.fcp_hdr; + srb_t *sp; + unsigned long flags; + uint16_t temp, c_flags = 0; + struct req_que *req = vha->hw->req_q_map[0]; + uint32_t req_cnt = 1; + uint32_t *cur_dsd; + uint16_t avail_dsds; + uint16_t tot_dsds, i, cnt; + struct scatterlist *sgl, *sg; + + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Alloc SRB structure */ + sp = qla2x00_get_sp(vha, cmd->fcport, GFP_KERNEL); + if (!sp) { + ql_log(ql_log_info, vha, 0x1100c, "Failed to allocate SRB\n"); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return; + } + + sp->type = SRB_NVMET_FCP; + sp->name = "nvmet_fcp"; + sp->done = qla_nvmet_fcp_done; + sp->u.iocb_cmd.u.nvme.desc = rsp_buf; + sp->u.iocb_cmd.u.nvme.cmd = cmd; + + ctio = (struct ctio_nvme_to_27xx *)qla2x00_alloc_iocbs(vha, sp); + if (!ctio) { + ql_dbg(ql_dbg_nvme, vha, 0x3067, + "qla2x00t(%ld): %s failed: unable to allocate request packet", + vha->host_no, __func__); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return; + } + + ctio->entry_type = CTIO_NVME; + ctio->entry_count = 1; + ctio->handle = sp->handle; + ctio->nport_handle = cpu_to_le16(cmd->fcport->loop_id); + ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); + ctio->vp_index = vha->vp_idx; + ctio->initiator_id[0] = fchdr->s_id[2]; + ctio->initiator_id[1] = fchdr->s_id[1]; + ctio->initiator_id[2] = fchdr->s_id[0]; + ctio->exchange_addr = atio->u.nvme_isp27.exchange_addr; + temp = be16_to_cpu(fchdr->ox_id); + ctio->ox_id = cpu_to_le16(temp); + tot_dsds = ctio->dseg_count = cpu_to_le16(rsp_buf->sg_cnt); + c_flags = atio->u.nvme_isp27.attr << 9; + + if ((ctio->dseg_count > 1) && (rsp_buf->op != NVMET_FCOP_RSP)) { + /* Check for additional continuation IOCB space */ + req_cnt = qla24xx_calc_iocbs(vha, ctio->dseg_count); + ctio->entry_count = req_cnt; + + if (req->cnt < (req_cnt + 2)) { + cnt = (uint16_t)RD_REG_DWORD_RELAXED(req->req_q_out); + + if (req->ring_index < cnt) + req->cnt = cnt - req->ring_index; + else + req->cnt = req->length - + (req->ring_index - cnt); + + if (unlikely(req->cnt < (req_cnt + 2))) { + ql_log(ql_log_warn, vha, 0xfff, + "Running out of IOCB space for continuation IOCBs\n"); + goto err_exit; + } + } + } + + switch (rsp_buf->op) { + case NVMET_FCOP_READDATA: + case NVMET_FCOP_READDATA_RSP: + /* Populate the CTIO resp with the SGL present in the rsp */ + ql_log(ql_log_info, vha, 0x1100c, + "op: %#x, ox_id=%x c_flags=%x transfer_length: %#x req_cnt: %#x, tot_dsds: %#x\n", + rsp_buf->op, ctio->ox_id, c_flags, + rsp_buf->transfer_length, req_cnt, tot_dsds); + + avail_dsds = 1; + cur_dsd = (uint32_t *) + &ctio->u.nvme_status_mode0.dsd0[0]; + sgl = rsp_buf->sg; + + /* Load data segments */ + for_each_sg(sgl, sg, tot_dsds, i) { + dma_addr_t sle_dma; + cont_a64_entry_t *cont_pkt; + + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + /* + * Five DSDs are available in the Cont + * Type 1 IOCB. + */ + + /* Adjust ring index */ + req->ring_index++; + if (req->ring_index == req->length) { + req->ring_index = 0; + req->ring_ptr = req->ring; + } else { + req->ring_ptr++; + } + cont_pkt = (cont_a64_entry_t *) + req->ring_ptr; + *((uint32_t *)(&cont_pkt->entry_type)) = + cpu_to_le32(CONTINUE_A64_TYPE); + + cur_dsd = (uint32_t *) + cont_pkt->dseg_0_address; + avail_dsds = 5; + } + + sle_dma = sg_dma_address(sg); + *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + avail_dsds--; + } + + ctio->u.nvme_status_mode0.transfer_len = + cpu_to_le32(rsp_buf->transfer_length); + ctio->u.nvme_status_mode0.relative_offset = + cpu_to_le32(rsp_buf->offset); + ctio->flags = cpu_to_le16(c_flags | 0x2); + + if (rsp_buf->op == NVMET_FCOP_READDATA_RSP) { + if (rsp_buf->rsplen == 12) { + ctio->flags |= + NVMET_CTIO_STS_MODE0 | + NVMET_CTIO_SEND_STATUS; + } else if (rsp_buf->rsplen == 32) { + struct nvme_fc_ersp_iu *ersp = + rsp_buf->rspaddr; + uint32_t iter = 4, *inbuf, *outbuf; + + ctio->flags |= + NVMET_CTIO_STS_MODE1 | + NVMET_CTIO_SEND_STATUS; + inbuf = (uint32_t *) + &((uint8_t *)rsp_buf->rspaddr)[16]; + outbuf = (uint32_t *) + ctio->u.nvme_status_mode1.nvme_comp_q_entry; + for (; iter; iter--) + *outbuf++ = cpu_to_be32(*inbuf++); + + ctio->u.nvme_status_mode1.rsp_seq_num = + cpu_to_be32(ersp->rsn); + ctio->u.nvme_status_mode1.transfer_len = + cpu_to_be32(ersp->xfrd_len); + } else + ql_log(ql_log_warn, vha, 0x1100d, + "unhandled resp len = %x\n", + rsp_buf->rsplen); + } + break; + + case NVMET_FCOP_WRITEDATA: + /* Send transfer rdy */ + ql_log(ql_log_info, vha, 0x1100e, + "FCOP_WRITE: ox_id=%x c_flags=%x transfer_length: %#x req_cnt: %#x, tot_dsds: %#x\n", + ctio->ox_id, c_flags, rsp_buf->transfer_length, + req_cnt, tot_dsds); + + ctio->flags = cpu_to_le16(c_flags | 0x1); + + avail_dsds = 1; + cur_dsd = (uint32_t *)&ctio->u.nvme_status_mode0.dsd0[0]; + sgl = rsp_buf->sg; + + /* Load data segments */ + for_each_sg(sgl, sg, tot_dsds, i) { + dma_addr_t sle_dma; + cont_a64_entry_t *cont_pkt; + + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + /* + * Five DSDs are available in the Continuation + * Type 1 IOCB. + */ + + /* Adjust ring index */ + req->ring_index++; + if (req->ring_index == req->length) { + req->ring_index = 0; + req->ring_ptr = req->ring; + } else { + req->ring_ptr++; + } + cont_pkt = (cont_a64_entry_t *)req->ring_ptr; + *((uint32_t *)(&cont_pkt->entry_type)) = + cpu_to_le32(CONTINUE_A64_TYPE); + + cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; + avail_dsds = 5; + } + + sle_dma = sg_dma_address(sg); + *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + avail_dsds--; + } + + ctio->u.nvme_status_mode0.transfer_len = + cpu_to_le32(rsp_buf->transfer_length); + ctio->u.nvme_status_mode0.relative_offset = + cpu_to_le32(rsp_buf->offset); + + break; + case NVMET_FCOP_RSP: + /* Send a response frame */ + ctio->flags = cpu_to_le16(c_flags); + if (rsp_buf->rsplen == 12) { + ctio->flags |= + NVMET_CTIO_STS_MODE0 | NVMET_CTIO_SEND_STATUS; + } else if (rsp_buf->rsplen == 32) { + struct nvme_fc_ersp_iu *ersp = rsp_buf->rspaddr; + uint32_t iter = 4, *inbuf, *outbuf; + + ctio->flags |= + NVMET_CTIO_STS_MODE1 | NVMET_CTIO_SEND_STATUS; + inbuf = (uint32_t *) + &((uint8_t *)rsp_buf->rspaddr)[16]; + outbuf = (uint32_t *) + ctio->u.nvme_status_mode1.nvme_comp_q_entry; + for (; iter; iter--) + *outbuf++ = cpu_to_be32(*inbuf++); + ctio->u.nvme_status_mode1.rsp_seq_num = + cpu_to_be32(ersp->rsn); + ctio->u.nvme_status_mode1.transfer_len = + cpu_to_be32(ersp->xfrd_len); + + ql_log(ql_log_info, vha, 0x1100f, + "op: %#x, rsplen: %#x\n", rsp_buf->op, + rsp_buf->rsplen); + } else + ql_log(ql_log_warn, vha, 0x11010, + "unhandled resp len = %x for op NVMET_FCOP_RSP\n", + rsp_buf->rsplen); + break; + } + + /* Memory Barrier */ + wmb(); + + qla2x00_start_iocbs(vha, vha->hw->req_q_map[0]); +err_exit: + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +/* + * qla_nvmet_send_abts_ctio + * Send the abts CTIO to the firmware + */ +static void qla_nvmet_send_abts_ctio(struct scsi_qla_host *vha, + struct abts_recv_from_24xx *rabts, bool flag) +{ + struct abts_resp_to_24xx *resp; + srb_t *sp; + uint32_t f_ctl; + uint8_t *p; + + /* Alloc SRB structure */ + sp = qla2x00_get_sp(vha, NULL, GFP_ATOMIC); + if (!sp) { + ql_log(ql_log_info, vha, 0x11011, "Failed to allocate SRB\n"); + return; + } + + sp->type = SRB_NVMET_ABTS; + sp->name = "nvmet_abts"; + sp->done = qla_nvmet_abts_done; + + resp = (struct abts_resp_to_24xx *)qla2x00_alloc_iocbs(vha, sp); + if (!resp) { + ql_dbg(ql_dbg_nvme, vha, 0x3067, + "qla2x00t(%ld): %s failed: unable to allocate request packet", + vha->host_no, __func__); + return; + } + + resp->entry_type = ABTS_RESP_24XX; + resp->entry_count = 1; + resp->handle = sp->handle; + + resp->nport_handle = rabts->nport_handle; + resp->vp_index = rabts->vp_index; + resp->exchange_address = rabts->exchange_addr_to_abort; + resp->fcp_hdr_le = rabts->fcp_hdr_le; + f_ctl = cpu_to_le32(F_CTL_EXCH_CONTEXT_RESP | + F_CTL_LAST_SEQ | F_CTL_END_SEQ | + F_CTL_SEQ_INITIATIVE); + p = (uint8_t *)&f_ctl; + resp->fcp_hdr_le.f_ctl[0] = *p++; + resp->fcp_hdr_le.f_ctl[1] = *p++; + resp->fcp_hdr_le.f_ctl[2] = *p; + + resp->fcp_hdr_le.d_id[0] = rabts->fcp_hdr_le.s_id[0]; + resp->fcp_hdr_le.d_id[1] = rabts->fcp_hdr_le.s_id[1]; + resp->fcp_hdr_le.d_id[2] = rabts->fcp_hdr_le.s_id[2]; + resp->fcp_hdr_le.s_id[0] = rabts->fcp_hdr_le.d_id[0]; + resp->fcp_hdr_le.s_id[1] = rabts->fcp_hdr_le.d_id[1]; + resp->fcp_hdr_le.s_id[2] = rabts->fcp_hdr_le.d_id[2]; + + if (flag) { /* BA_ACC */ + resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_ACC; + resp->payload.ba_acct.seq_id_valid = SEQ_ID_INVALID; + resp->payload.ba_acct.low_seq_cnt = 0x0000; + resp->payload.ba_acct.high_seq_cnt = 0xFFFF; + resp->payload.ba_acct.ox_id = rabts->fcp_hdr_le.ox_id; + resp->payload.ba_acct.rx_id = rabts->fcp_hdr_le.rx_id; + } else { + resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_RJT; + resp->payload.ba_rjt.reason_code = + BA_RJT_REASON_CODE_UNABLE_TO_PERFORM; + } + /* Memory Barrier */ + wmb(); + + qla2x00_start_iocbs(vha, vha->hw->req_q_map[0]); +} +#endif diff --git a/drivers/scsi/qla2xxx/qla_nvmet.h b/drivers/scsi/qla2xxx/qla_nvmet.h new file mode 100644 index 000000000000..5c9e793116bd --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_nvmet.h @@ -0,0 +1,130 @@ + +/* + * QLogic Fibre Channel HBA Driver + * Copyright (c) 2003-2017 QLogic Corporation + * + * See LICENSE.qla2xxx for copyright and licensing details. + */ +#ifndef __QLA_NVMET_H +#define __QLA_NVMET_H + +#include +#include +#include +#include + +#include "qla_def.h" + +struct qla_nvmet_tgtport { + struct scsi_qla_host *vha; + struct completion tport_del; +}; + +struct qla_nvmet_cmd { + union { + struct nvmefc_tgt_ls_req ls_req; + struct nvmefc_tgt_fcp_req fcp_req; + } cmd; + struct scsi_qla_host *vha; + void *buf; + struct atio_from_isp atio; + struct atio7_nvme_cmnd nvme_cmd_iu; + uint16_t cmd_len; + spinlock_t nvme_cmd_lock; + struct list_head cmd_list; /* List of cmds */ + struct work_struct work; + + struct scatterlist *sg; /* cmd data buffer SG vector */ + int sg_cnt; /* SG segments count */ + int bufflen; /* cmd buffer length */ + int offset; + enum dma_data_direction dma_data_direction; + uint16_t ox_id; + struct fc_port *fcport; +}; + +#define CTIO_NVME 0x82 /* CTIO FC-NVMe IOCB */ +struct ctio_nvme_to_27xx { + uint8_t entry_type; /* Entry type. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + + uint32_t handle; /* System handle. */ + uint16_t nport_handle; /* N_PORT handle. */ + uint16_t timeout; /* Command timeout. */ + + uint16_t dseg_count; /* Data segment count. */ + uint8_t vp_index; /* vp_index */ + uint8_t addl_flags; /* Additional flags */ + + uint8_t initiator_id[3]; /* Initiator ID */ + uint8_t rsvd1; + + uint32_t exchange_addr; /* Exch addr */ + + uint16_t ox_id; /* Ox ID */ + uint16_t flags; +#define NVMET_CTIO_STS_MODE0 0 +#define NVMET_CTIO_STS_MODE1 BIT_6 +#define NVMET_CTIO_STS_MODE2 BIT_7 +#define NVMET_CTIO_SEND_STATUS BIT_15 + union { + struct { + uint8_t reserved1[8]; + uint32_t relative_offset; + uint8_t reserved2[4]; + uint32_t transfer_len; + uint8_t reserved3[4]; + uint32_t dsd0[2]; + uint32_t dsd0_len; + } nvme_status_mode0; + struct { + uint8_t nvme_comp_q_entry[16]; + uint32_t transfer_len; + uint32_t rsp_seq_num; + uint32_t dsd0[2]; + uint32_t dsd0_len; + } nvme_status_mode1; + struct { + uint32_t reserved4[4]; + uint32_t transfer_len; + uint32_t reserved5; + uint32_t rsp_dsd[2]; + uint32_t rsp_dsd_len; + } nvme_status_mode2; + } u; +} __packed; + +/* + * ISP queue - CTIO type FC NVMe from ISP to target driver + * returned entry structure. + */ +struct ctio_nvme_from_27xx { + uint8_t entry_type; /* Entry type. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t handle; /* System defined handle */ + uint16_t status; + uint16_t timeout; + uint16_t dseg_count; /* Data segment count. */ + uint8_t vp_index; + uint8_t reserved1[5]; + uint32_t exchange_address; + uint16_t ox_id; + uint16_t flags; + uint32_t residual; + uint8_t reserved2[32]; +} __packed; + +int qla_nvmet_handle_ls(struct scsi_qla_host *vha, + struct pt_ls4_rx_unsol *ls4, void *buf); +int qla_nvmet_create_targetport(struct scsi_qla_host *vha); +int qla_nvmet_delete(struct scsi_qla_host *vha); +int qla_nvmet_handle_abts(struct scsi_qla_host *vha, + struct abts_recv_from_24xx *abts); +int qla_nvmet_process_cmd(struct scsi_qla_host *vha, + struct qla_nvmet_cmd *cmd); + +#endif