From patchwork Wed Sep 26 04:03:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Madhani, Himanshu" X-Patchwork-Id: 10615277 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EF728112B for ; Wed, 26 Sep 2018 04:27:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DB40A28A52 for ; Wed, 26 Sep 2018 04:27:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CF63A2A5E3; Wed, 26 Sep 2018 04:27:14 +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=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,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 2D8CF28A52 for ; Wed, 26 Sep 2018 04:27:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726372AbeIZKiJ (ORCPT ); Wed, 26 Sep 2018 06:38:09 -0400 Received: from mail-sn1nam02on0043.outbound.protection.outlook.com ([104.47.36.43]:34958 "EHLO NAM02-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726375AbeIZKiJ (ORCPT ); Wed, 26 Sep 2018 06:38:09 -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:X-MS-Exchange-SenderADCheck; bh=vq+Ia8D5Gl5+4909g6Sh/A24qXoYp+FdV8uq7b+q9+k=; b=DAF3icswk5mSD59Kz6FCPUZyYQpVEi1E0KcA1iKBl8Nfvhiouf0/rzD0Hmc0y13HxyqUprZ1JVmobjIOjzmTnyG1+sbjiFihvGz5ZU8agiyht49HnfuPVhhYkepKH1KmioFeNO2DDvc925J8iWFmJqYVRNPi2LTZFRC0XmSFPMo= Received: from CY1PR07CA0019.namprd07.prod.outlook.com (2a01:111:e400:c60a::29) by SN1PR07MB1454.namprd07.prod.outlook.com (2a01:111:e400:5838::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1122.16; Wed, 26 Sep 2018 04:26:57 +0000 Received: from DM3NAM05FT058.eop-nam05.prod.protection.outlook.com (2a01:111:f400:7e51::203) by CY1PR07CA0019.outlook.office365.com (2a01:111:e400:c60a::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.1164.20 via Frontend Transport; Wed, 26 Sep 2018 04:26:57 +0000 Received-SPF: Pass (protection.outlook.com: domain of cavium.com designates 50.232.66.26 as permitted sender) receiver=protection.outlook.com; client-ip=50.232.66.26; helo=CAEXCH02.caveonetworks.com; Received: from CAEXCH02.caveonetworks.com (50.232.66.26) by DM3NAM05FT058.mail.protection.outlook.com (10.152.98.174) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256) id 15.20.1185.5 via Frontend Transport; Wed, 26 Sep 2018 04:26:56 +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; Tue, 25 Sep 2018 21:03:41 -0700 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 w8Q43erj009754; Tue, 25 Sep 2018 21:03:40 -0700 Received: (from root@localhost) by dut1171.mv.qlogic.com (8.14.7/8.14.7/Submit) id w8Q43edd009753; Tue, 25 Sep 2018 21:03:40 -0700 From: Himanshu Madhani To: , CC: , Subject: [PATCH v2 1/5] qla2xxx_nvmet: Add files for FC-NVMe Target support Date: Tue, 25 Sep 2018 21:03:35 -0700 Message-ID: <20180926040339.9715-2-himanshu.madhani@cavium.com> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20180926040339.9715-1-himanshu.madhani@cavium.com> References: <20180926040339.9715-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)(376002)(346002)(39860400002)(396003)(136003)(2980300002)(438002)(189003)(199004)(1076002)(47776003)(11346002)(48376002)(106466001)(478600001)(51416003)(87636003)(76176011)(6346003)(446003)(336012)(34290500001)(72206003)(6666003)(86362001)(186003)(126002)(476003)(2906002)(8936002)(486006)(26005)(106002)(14444005)(80596001)(2616005)(36756003)(110136005)(305945005)(356003)(42186006)(8676002)(16586007)(44832011)(81156014)(5660300001)(54906003)(50226002)(69596002)(81166006)(50466002)(316002)(4326008);DIR:OUT;SFP:1101;SCL:1;SRVR:SN1PR07MB1454;H:CAEXCH02.caveonetworks.com;FPR:;SPF:Pass;LANG:en;PTR:50-232-66-26-static.hfc.comcastbusiness.net;MX:1;A:1; X-Microsoft-Exchange-Diagnostics: 1;DM3NAM05FT058;1:J/WV5jFyZ/uG70hWIAQdCBBD2WwDMWGY0aBS3+1YTs8NkRX0rVdQZVqc5tZ3DjCX1s82TnL98CbXqT4X9r7A2jfsM3w9HFbzPbtpEfzPMsiA9t7akb5FyHizJ2zpO3NK X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 0e927d24-53ed-49ba-c9c2-08d623684b80 X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:(7020095)(4652040)(8989299)(4534165)(4627221)(201703031133081)(201702281549075)(8990200)(5600074)(711020)(4608076)(2017052603328)(7153060);SRVR:SN1PR07MB1454; X-Microsoft-Exchange-Diagnostics: 1;SN1PR07MB1454;3:mChCJlAXPOGL72AW9NTLKaivXHT71A+/mvxMjpe/Bl7dMBEZBrhimK3z/gFKAbT+JmCJBQuRU9b7VQC8zA2pAFjJIxQKJdIMFolnKuXp7enkyToHD/OYYrHSyIkGLmVpgIiunDPVxxTeMBsjKKCkvULMlPlP+z+q9hvneZzJHL+ZLLfNx9/l9kK58J0hPcXTfkjsZw9P5ScifakMBBbT/D3569NBUXM7XrLsW6pweQz6oPGX6lruTiBVhQZCk9TdBcjsX3EFxjc2V3bwCT+38JuyCkzeZIb8qYW4JzE7JeZ+CDLG0p9Xk2YlDrDOYs6RTw2OhvY5tJA630MS3lgItzPfmiY86MjDBxdk6sLRao0=;25:bdstLy91peGjymKszVxQ25lhjjmDMEH75p2Zd7fJriP87z91rPlWAr9ETMV3MBfOO6Z3er1HS/M4jhESiNctIbFCGL47RFlEVlEtAMUbEQKbjntCVcDLhQkzd81SbGGK/t+L1beyIIt860u+sYOdsRk7SY3dRo82oHm2lj7JV6Bfhome7uZttAx5hwL9g/zDhKH0Ez2hRnEy+/BIXSftqRV+ADnVR7E8x4i2u2m8x/yfMABrIHa9A0+rLfpeFkbHmWqJjgvtD3yVDWUcwhC9Zj+6oMVuUbrzZr56EI3ZqTCXXzzXTsf0KQ/SHNrB9tGX2llhKrI4uhLYRpC4JvsTNQ== X-MS-TrafficTypeDiagnostic: SN1PR07MB1454: X-Microsoft-Exchange-Diagnostics: 1;SN1PR07MB1454;31:EtMAYSxgmLjBaLi9qSZNttZ0V53501qWsm0fK0koD3f/F+96GxgsFru274q0Qmo3f2R+pI5aZ5ctl8tkHpMoinwPxl/KKP3LBq/8ZnAM3cFThzjFATBZ1x25QYbBo/z16kuEEX53uCDHMw8rc0XLXDmIxkuPNdiTHP8PS2O8X5sAAce1G2bg+rBFJ4wGHeqczPJyMgvMGkgxKQ9hlYu+asBP3AQqi+4XhGWNWrTAesk=;20:Gjs1zwCXprXvjfHZ/+A6RxKr8nx5qvEpHH8L2LtmjX/7v90IK95EDW8wPsRrt/tp6zsc9chRXedjdyWSNFO5144+Nc4y6+rVo7EKIN05SXkxARTxtGmM8x6XEOJ6suygOrnaWzJwUdhi0NkWqhHt7QVjv5WI8hAVxtE0vGuB/FiayAVK94kay+jeXEKXvnE2KcoGBhg595f1xW6NsmKf2ThxRMZEtb3sf5PP64ny5ltFOpBIzJmQiGBccvpRFB9CxynxHh8P3OE+Ge5yHZgfiF5JWIumyr2YhkY4s+MHUgfaNlFVNd3FkuZAPuzaAbdlFs90S0tSYzqbfrk/Z7Gn2Xc1Pl2qQ8BS3/4FsfluGsVXDvj4QxOllzSswem0d2RHlT2/jsf/6C6+3utUAL/oQJchz/erLmznmaPLodpMzI+WPfMymPyR5Jxc+9VePbnsQix+pyAQWDl0vbiYkUAwGrH82hBaFBBBtXBGtUsCMi2ZGuQsBXuQ1D80MvASA+Lt X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(8211001083)(6040522)(2401047)(5005006)(8121501046)(93006095)(93004095)(3231355)(944501410)(52105095)(3002001)(10201501046)(149066)(150052)(6041310)(20161123564045)(20161123562045)(20161123560045)(20161123558120)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(201708071742011)(7699051)(76991041);SRVR:SN1PR07MB1454;BCL:0;PCL:0;RULEID:;SRVR:SN1PR07MB1454; X-Microsoft-Exchange-Diagnostics: 1;SN1PR07MB1454;4:dSn3+9YBlNiv7I3ihPJ2QKzJeqEFk+aG0clXn6Ac9jaVd7YvctLtKbAgaRPxL3ra3FNBstlO0x45PvXycH2QWD3Q5JaslUsIwumeiPQpzX8xEtw/NiSq4e2QACaKNbzKxuAeQJb+sCDvyCtQOAQ+w8w9qSBSOsaYEOtkUzlGCM/wpso71yunpb2Vfa6c+J3ThR/8zffBI65qqKFBLb5QF9XqtQrl6sQYcztr9ljy1ox+BOXyLmz9EJ38liA+ZibWWrSMH8C1a2ULJJibk4IzmQ== X-Forefront-PRVS: 08076ABC99 X-Microsoft-Exchange-Diagnostics: 1;SN1PR07MB1454;23:Dl9HKz0a9jHFyT06apLhWuayev5FbnUzeHEXWYhqiq7VxNI0pM2RBnOftufZyy8IhWPWxIaMHF85mLPyH1Ri3Em+TnpqR6CRX7rm9HIf5mvE1AtgdEmYS+GgNX7aFpgUA0VtRiXE76ro8m06WizMB9g0vz28YQUn5PTvsfCYN8QTe/t3H75Faw8o0+RqHsmZuAUw/c4RjbuzcN/GkbFOGCy9l0Ah+kjRSH66hSlQpbU7BFoLS/ingvx16iVWD1S9F4t6mu36YKXve02SqVdVOYPU4GoFLMCSEXWiw75K0ybPuThpVwc6ZkPHmgBTxUq9E5Ubd1m7ERDgNhcYJc18w4+l7lRcxdJQilm/35RFo2g+Q70SemAlWc5zLVCs+w00qq9oRC5A6uLuGpjrrplJHnwhFOZgkKAxpbiW9Y/BT6Qb/ZLeY6g2X/KH/QmHIwOoNeBfIFGqnsSmOBEQdoe4JubV2Uf7CRExUk18WNAQzA+vqYz1IebygJhqOaqS26N1kaHmlAYlJ/DjPJmEttJbybJU81LiGCRs9eWz8K5NS8zg3ACPBxSvdW7WOFGDEVmK2Jwc37CCK8KAmGYfWVzOncXZTvNzhoR8xYCn1UehYzAyuN5RVq4CZjQXtIYhK4QhU2hVmrrjqX3uNPapTpnMQfLoB0pemqkse3q/glrP9D5h4u/XabjdShn/nRmkYtOIFdPhNcroKZ0cVltBIx580Vg8eDRmDR1VerSvddW+GGwioPuaGnr8ltg7hGresZDO8w49o5GLLNfZCgeppyF0J++WdQI2qnVbCscfIfK6Oyb/JZVXB1hkCAdL62BqWDRWeouLRD3FzoRsgfYfzLSfQf3MjtB5z6rPqdAqRkpY/GopI6XF//2vEESrZ+xxNf2hSzx2eJidnUEdPC3lcPwOLDdwm94JQ3B9O1FAxsyXgUObUTGHQhFbr7Ci8oiyROZz/RbNMccssswiayRYtAFmwqq0w54hTaH7W4f5u3+mdOVJJYVz5O6fp70Va2labUL7JWp7aEhKT3BP2szDm+CAAQmo9niN64Hsq6EgSArC+o8g0gXCrGEzsNNLKluuecS0Fe6hdTXlmzaY93c+U/7BLB5JOTeP4VMLY20FmY2b+obMDv7KPBNRioXaQwUOB37Fb05kzotbw5+fCGXe/Z7Coi98DQ4WpoH+6yUG+0kulLw= X-Microsoft-Antispam-Message-Info: O+zp0xasFv46qxkmWsY2KkzjEPf5nR2gNlWkcBdW4aIaZkc5TdtcuGrzefyqKUzGWX9IH2fYcCRDFpBea/fCMJt0gq/gTwWZUx4rwScj/QH7sFcc9zkogCpIQKYJPw9mMPNCbJd0Yzlxn+4oFVSD/DxIti/x+rnlvaTg30qwvULEdy1oDwGtMo9n0HPE3SDKmLJnK+AAnyii6aepyWMQwVzO5KyANLSBHjb7PWuaygjwUu70p6nIn4vDCgDgAPE8z+6D9rN158+I3ldxTt0YsG8dS67znVL6bQN8X7KA2TbKe9Iseb3ssYjeOg8tZRRx8YHD6PULmVzEqbCARBVSKMqgLvH+3QjlLus/yorskE8= X-Microsoft-Exchange-Diagnostics: 1;SN1PR07MB1454;6:7mZyeFf506yvR4Y4s872f+XERGcmkvIlThtD8CL3/OkfYQFaofWuztpOUuqpJl967SGUHbldic0PaOTVBCyC2sQ5ZqpKS6bEKyApAiNOAkUyTTWpSVEuj2HRmRqe+Lhe0L+Z0fgReTDK0x6PPjlLbBbE5E1sRy9fISLFdAETZBm1FcXLw1Gwo2KEbavIVJ3mZbKuKCRFl1yQvwOZEG/I0xwRg6VkexRgjTFG7WsNNEdSmBli8dkoUWw3TDOCs8rn5dEcXZTgShrbPTiYP8R7O5ACFypzFEQf9LNBDVzjTRxs3AfwY/qkJgRWX9bvwOR4TwnkgPCteFswFTW+monXZmTkfPMleSfeJR1lAgJQLzrzZ6S0Y2PY5Ipf0iVE4PvrgaTY4W1/ykp2LrxL5gaacmDTkFyeSehzZ1Xo8MNfdu/9V4au0EHTcTdrYdAvW7eorF1biXYa/0kcfJKZUiwywA==;5:h86n2WaeFxG9KCXinOlyfz1WpCpnayEy4Fy6Zy8U0ND1VSXVmDfYNU9Gx37K+VrCYaICmwnScARk6yDqScIIOxJ0yJn8EG6UWTJckmNCN+7xUQtjtuXohQxnrLCyBPOhmaV6MEkDt8QppbPw6EjtqF++MtkHPKboziTIhaMfSLg=;7:Tsx55q2hHD+hvpl5eGPQvWQqu/I70Mh4gUABSYMtPQprBE9MfJum79bmn/h9dZo6U1C5AJy6yCW0T4QMfy1LpF5CCfjVzWKbmORw/t/kVlnYT8JPZsEH8aDtNSvNHiObFnS6ZHHcilBMRUdStezSXTGvCBiVrxlB+VdCp2IG0sW9SbUaFFt552ByKnAp3dEzW+QX4wv9IexVCk4mbhP6ahPiA42cR4nNyyoC1tsHI+2B6uzn3Oxhss9ajiia2tSE SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Sep 2018 04:26:56.5274 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 0e927d24-53ed-49ba-c9c2-08d623684b80 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: SN1PR07MB1454 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 This patch adds initial files to enable NVMe Target Support Signed-off-by: Anil Gurumurthy Signed-off-by: Giridhar Malavali Signed-off-by: Darren Trapp Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/Makefile | 3 +- drivers/scsi/qla2xxx/qla_nvmet.c | 798 +++++++++++++++++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_nvmet.h | 129 +++++++ 3 files changed, 929 insertions(+), 1 deletion(-) create mode 100644 drivers/scsi/qla2xxx/qla_nvmet.c create mode 100644 drivers/scsi/qla2xxx/qla_nvmet.h diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index 17d5bc1cc56b..ec924733c10e 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile @@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \ - qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o + qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o \ + qla_nvmet.o obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o obj-$(CONFIG_TCM_QLA2XXX) += tcm_qla2xxx.o diff --git a/drivers/scsi/qla2xxx/qla_nvmet.c b/drivers/scsi/qla2xxx/qla_nvmet.c new file mode 100644 index 000000000000..5335c0618f00 --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_nvmet.c @@ -0,0 +1,798 @@ +/* + * 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" + +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; + + if (!IS_ENABLED(CONFIG_NVME_TARGET_FC)) + return; + + complete(&tport->tport_del); +} + +/* + * 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; + + if (!IS_ENABLED(CONFIG_NVME_TARGET_FC)) + return; + + 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; + + if (!IS_ENABLED(CONFIG_NVME_TARGET_FC)) + return 0; + + /* 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; + + if (!IS_ENABLED(CONFIG_NVME_TARGET_FC)) + return; + + /* 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; + + if (!IS_ENABLED(CONFIG_NVME_TARGET_FC)) + return; + + 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), +}; + +/* + * 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) +{ + struct nvmet_fc_port_info pinfo; + struct qla_nvmet_tgtport *tport; + int error = 0; + + if (!IS_ENABLED(CONFIG_NVME_TARGET_FC)) + return 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); + return 0; +} + +/* + * qla_nvmet_delete - + * Delete a targetport. + */ +int qla_nvmet_delete(struct scsi_qla_host *vha) +{ + struct qla_nvmet_tgtport *tport; + + if (!IS_ENABLED(CONFIG_NVME_TARGET_FC)) + return 0; + + 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); + } + 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) +{ + struct qla_nvmet_cmd *tgt_cmd; + uint32_t size; + int ret; + uint32_t look_up_sid; + fc_port_t *sess = NULL; + + if (!IS_ENABLED(CONFIG_NVME_TARGET_FC)) + return 0; + + 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) + 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; +} + +/* + * 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) +{ + int ret; + struct atio7_nvme_cmnd *nvme_cmd; + + if (!IS_ENABLED(CONFIG_NVME_TARGET_FC)) + return 0; + + 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 ? */ + } + 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) +{ + uint16_t ox_id = cpu_to_be16(abts->fcp_hdr_le.ox_id); + unsigned long flags; + struct qla_nvmet_cmd *cmd = NULL; + + if (!IS_ENABLED(CONFIG_NVME_TARGET_FC)) + return 0; + + /* 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); + + return 0; +} + +/* + * 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; + + if (!IS_ENABLED(CONFIG_NVME_TARGET_FC)) + return; + + 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_ATOMIC); + 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]); +} diff --git a/drivers/scsi/qla2xxx/qla_nvmet.h b/drivers/scsi/qla2xxx/qla_nvmet.h new file mode 100644 index 000000000000..188ad2c5e3f1 --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_nvmet.h @@ -0,0 +1,129 @@ +/* + * 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