From patchwork Wed Dec 20 06:56:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Madhani, Himanshu" X-Patchwork-Id: 10125059 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 7A7346019C for ; Wed, 20 Dec 2017 06:57:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6DB782964E for ; Wed, 20 Dec 2017 06:57:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6070629649; Wed, 20 Dec 2017 06:57: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=-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 BDFA129649 for ; Wed, 20 Dec 2017 06:57:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932422AbdLTG5L (ORCPT ); Wed, 20 Dec 2017 01:57:11 -0500 Received: from mail-bl2nam02on0088.outbound.protection.outlook.com ([104.47.38.88]:33568 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932380AbdLTG5F (ORCPT ); Wed, 20 Dec 2017 01:57:05 -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=nKzs9wHGlvfqlq5jwybe2WeFs9CBrhz8rYW54mKltOM=; b=ZaPAK2IP62U51KvUC/bcnDzN2u0Arr85Cg3+tPlGQie/Q1I8LqFzs+WJe57CYhicI1ANQH2sk5h+8vpBos+jzLW0nZBPtfwuGOXfZFU7zWV2ayiyMx9/KJ70zlONdt5k62D1s4UyBixjovnACu1YplTv+SINc64romHRMCCpu3U= Received: from SN4PR0701CA0020.namprd07.prod.outlook.com (10.161.192.158) by CY1PR07MB2522.namprd07.prod.outlook.com (10.167.16.13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.282.5; Wed, 20 Dec 2017 06:57:02 +0000 Received: from BN1AFFO11FD027.protection.gbl (2a01:111:f400:7c10::106) by SN4PR0701CA0020.outlook.office365.com (2603:10b6:803:28::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.323.15 via Frontend Transport; Wed, 20 Dec 2017 06:57:01 +0000 Authentication-Results: spf=permerror (sender IP is 50.232.66.26) smtp.mailfrom=cavium.com; vger.kernel.org; dkim=none (message not signed) header.d=none; vger.kernel.org; dmarc=none action=none header.from=cavium.com; Received-SPF: PermError (protection.outlook.com: domain of cavium.com used an invalid SPF mechanism) Received: from CAEXCH02.caveonetworks.com (50.232.66.26) by BN1AFFO11FD027.mail.protection.outlook.com (10.58.52.87) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.20.302.6 via Frontend Transport; Wed, 20 Dec 2017 06:56:48 +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, 19 Dec 2017 22:56:46 -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 vBK6ukvM021574; Tue, 19 Dec 2017 22:56:46 -0800 Received: (from root@localhost) by dut1171.mv.qlogic.com (8.14.7/8.14.7/Submit) id vBK6ukgJ021573; Tue, 19 Dec 2017 22:56:46 -0800 From: Himanshu Madhani To: , CC: , Subject: [PATCH 07/43] qla2xxx: Add ability to track IOCB resource for FW Date: Tue, 19 Dec 2017 22:56:08 -0800 Message-ID: <20171220065644.21511-8-himanshu.madhani@cavium.com> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20171220065644.21511-1-himanshu.madhani@cavium.com> References: <20171220065644.21511-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)(39380400002)(39860400002)(396003)(346002)(376002)(2980300002)(448002)(199004)(189003)(50466002)(48376002)(51416003)(47776003)(87636003)(85326001)(106466001)(316002)(86362001)(72206003)(1076002)(575784001)(50226002)(305945005)(4326008)(8936002)(69596002)(54906003)(16586007)(42186006)(36756003)(76176011)(478600001)(5660300001)(80596001)(110136005)(8676002)(2906002)(59450400001)(6666003)(81166006)(356003)(81156014)(2950100002); DIR:OUT; SFP:1101; SCL:1; SRVR:CY1PR07MB2522; H:CAEXCH02.caveonetworks.com; FPR:; SPF:PermError; PTR:50-232-66-26-static.hfc.comcastbusiness.net; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BN1AFFO11FD027; 1:MTsUPo48Jd/JWqZhCqEvdJugrCUFWPXMeM2TVBG1z3RPtSAm1hLKwJc62DQpvbV6ZCdh72ioXuT25QTJaaealq87cwO0cKxLys9+n0nqvpWvl2T9AV9EdO//Zr0GE1Ed X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 6e6135b8-aecc-4701-fc2f-08d54776d75d X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(5600026)(4604075)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603307)(7153060); SRVR:CY1PR07MB2522; X-Microsoft-Exchange-Diagnostics: 1; CY1PR07MB2522; 3:Gtiy4fdV6Y253YDWOXTDESkbpDtQFSCJ01S6np7kEOr6wgBrxRsmK42Ohhw80vsogwqiNiN85vvTQqXmRTpbiH48scWD2OyMJFUNvdKgOoJwpAykLFPcOiC+4kum51cnMe7pkkxkt4tkDRGQ1xzJDZnCAhE4DbyQxPM2d2WE92ztHugvbra/iPwY3g/vVQv0i+VNgeMK6cd9HwcIi+zrLXymn3AUJOjWijs4JQjQir6WrW08f35EfXXgT6i/HKf77aV8zf69t6PoG7dWr6yRCx100yjdlAbxEyS+cyZaaSv1ZUhkp3z51hfjFYjkGQJ/vg0TIRP7wMaYHPanJGLwcH+AF0aaCY9l4dhUVzaMNgg=; 25:TgjzhI4RPBVBZtoCZFYJCeuk6G12YjuXN5b0r1lSI5gDmp0s5bq9VAhsmjAzOyrXAnZM2/pJ5LI/txS/4C2wibim2LAtQApOTfwVAZrky6peKPHimDDU0mB/Oot60Ut5tgNoNc1zfwQPeI74kUMbZCIkEDLWoQpCMAMg1KoHlx7uF1EqbamNu7mE2SAiYfd4iBIKU2675RqtSSa46lbYXn+YjC3/5wP7CApYmDOIjnxlvlMmRTzk/iY5waCmgJ9RhcLblHb6ewr2amGcJ8yG4WFvYGCLbCMWTPY8Mv9strtntQjNPyJcePRSac9hkMNeiqdr96CbUYceS3Gzr4rDMg== X-MS-TrafficTypeDiagnostic: CY1PR07MB2522: X-Microsoft-Exchange-Diagnostics: 1; CY1PR07MB2522; 31:mbme5ulbKeSIZ2wgH8JtUngZwtV1hC61Tzdnn1NxTgCm+564kLuXpCMU5PztyRj3aatLVlomyp82u+9F3inoEp5XTGEzu8n1CUsLh7vD/qY5KVO8uiZC0b1sARODyv2Q21nWQ6iEMvJoSKKTcxdTyJWaSQ48wt4bwPVTWYnPFkNqpQ0CazAgpdXpV4XuRqO7IZJKDJm7fMKZ2EjqQ3kYSZZTgu13/EHrUpWMl3Qk9vw=; 20:rCNlu/14tLQzuHHmMv2+iLG47aToyxe0XG5ajks5AuykCEoSxbsWcDFik2KBq0G2250KTQ63YlUSHOXE9Z5cGj7iSP/PAbaz+f5Z7+8qxpTLFEM9Ac/27jg+b6Zg5lkSykFd1w+IfPh/oeIGldF38c5FhKthoTEeBVWw0G0SkBQNPNv+4aXRwgIs945T/MSvH+94SBxDq9tj0JvJX07qu16Q+Q8cayRToaqXJzssgMn3ODO3zH4VQePIr3McKUucctLMFAW8oTlxx/TGDDoJ2LpYE0MMGnd7C7zHlDlheikc8uItLjaPHE/U5RqHFnKsqt7lYDCuVyEhBAw1MMnzeNkP9Th6w4U9VZmn79jZoFmKTwym1QQvYQ7XuwSGYexdKiSAPCEbfsB9S6fgR5o4WC+62CBuaB8nFE27EYrAxxK17qlqNv929PFiI7tmXIa6EAZf9IhodeiRCUDUEyJd0P6UbGLP6GR3gaXnQvHn3ziimOZf8Slkxwya32txeKqb X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040470)(2401047)(8121501046)(5005006)(3231023)(93006095)(93001095)(3002001)(10201501046)(6041268)(20161123560045)(20161123564045)(20161123562045)(20161123558120)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(6072148)(201708071742011); SRVR:CY1PR07MB2522; BCL:0; PCL:0; RULEID:(100000803101)(100110400095); SRVR:CY1PR07MB2522; X-Microsoft-Exchange-Diagnostics: 1; CY1PR07MB2522; 4:3Eoroj/1Nhqztq08qxbkzAAKuXmTOVNhxcafzyQDNGQ0Kezf3RzQ8/gLD8rFwe6Tuc2+wQZybZqfK3q8u/SAltkbTDLUhgLvdX7LCutfoHewikXqIyZW3Mr8UblKY4UUaAX1tWxk9yzu8NJcrVLklXS9/CDQobBWa0aBAqU6iq7JNqdXqGfASNTosAF2J+OUaFtQ6iR47lbUVdQr/q/obaceMX355RYMS0UhKAiRFLrVEIhMSmj7lrjXLVoVofmlx+lnOBc90sRASNTsyCktiA== X-Forefront-PRVS: 0527DFA348 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CY1PR07MB2522; 23:XvV9fVW3mrmFZSCP818rVXs9Ab4JGbuR+COXeOsLF?= =?us-ascii?Q?UyLkG5F4x632iQ79zvhqSW03U7HO0ZVb9h3kZjPYDR6agtCEH9xnAtwd6DMK?= =?us-ascii?Q?JXu+U/7tQDi8C/AknqU0Jn1ZZ3yN7bZ/9PXVdAJVqHfsJMmCgW37Bj+cVFdo?= =?us-ascii?Q?1mBgTKfuSbRhsU+OTB5ahwqIVSL7JmoJcBxjhOhHc9zIdaEUT8wk4A1iWDwr?= =?us-ascii?Q?AWIJsgxtEXZLy2vEBuiixiLZvNKY+6Vn1SCsaJzdFL7i9GHQTyQEZVV+hQzW?= =?us-ascii?Q?Bw/i/thFdx9uUyq1F7T1Sk2b8lwDS0fjuvwOFwphqjcbplOqePT4MJwjNnon?= =?us-ascii?Q?sftGPjF46aM/AkYa1Nim8uFWlRg5XzdKV6XCLI84AJGBvBh56Ku7c3wbmXAE?= =?us-ascii?Q?YNv5kjOT1h/zxdva+BgxhL2m/5YUnGOIAQgpQ/2vFGU3TgrJs1jWxmo/aDfB?= =?us-ascii?Q?uYUll9UzeDeaegSS2CroiKsCsKFpDIA/bJBa9GHOe+qWyWy/qFmw0hRYbHEM?= =?us-ascii?Q?7sLSx8pJujZYXkSKmO/Kdhh1xUWWsL3a3aCUJkcdyjUpzjUx5c3zGq+uppmc?= =?us-ascii?Q?tpjyXzpF5YZi9RzaYg/w9mezUbNumkWpUG8t2j4WI9IqOUnnmxQhrMHrP93f?= =?us-ascii?Q?1rknhp2bcUAFRyNE+liENWq4c5lRbQ4pA+kEIzycNBfRXALtLNPGAEDMj5w3?= =?us-ascii?Q?B6JGK4SFvk1Zmm0aw2dIbPtsi//C5xlqriTq4Ofobr3gHohA/wubKwqsHaAj?= =?us-ascii?Q?uLmV02V6Jx0hZiZOZpHkVMKh/fZgaZ2KA4Mb4xErXNXfd5+++9K8rSrCNMv7?= =?us-ascii?Q?RuhcsYX/NTFzKCB3Wsdh/4lngRO7Prw4ib8lolh0VHTIRUejo3UkFtGIwrQ1?= =?us-ascii?Q?P33E0l3rQV9VGfhgjmlHSrvAQFp7fCd/DDh7Cfi7TFNps75DIHzg7d8wsDw7?= =?us-ascii?Q?CcWMx6u+HMtNmQVKe54FZyUAWZu8Mmkhrr0Z/9emblY6TJGmqYOA4wqd3sV6?= =?us-ascii?Q?F/6XzzcVnWsDytwxHGcqFaURHZRaAk8KNivcyeaj43EUQ=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1; CY1PR07MB2522; 6:mEjz6V+xfSYms8OnXbbTfVqiEitPTNywVW9s0Og4e+iqeO3O/paXJTcczeYWZswnIMs9ZFx5oUcISw6pC2HepFEeUZNWdoXu22QpY0+NoxzYuMGPDmVvcdFMR4TnqZ8bU9TDZh1IqpUlUnQ/J2CGB4sUGpK7/t9y0wTD7+W9KL4ZXzzuUJLQB5/4W8NVyRcYGXPPqHzonr+XnqKEcgyBKof7QFQp2wrqAvFon3Lnaj8qeX1KLjaCKVKL6iwkCQb1t0zUQXtgcBoOqpoM2zXBIXv0pVrn6mTfenxPoLnusq2jWIY/vwEpsmA9hPe1/pHQTYJ1U/uObbiQftozC5nw8nz5CVdHUi+qaMBcuHeBR4w=; 5:69yKGQkRiKmt/xtNbAvvxPx5z5mndOjDoiQoe20Pw733yxYxSSFz9wXMDAUwFeliyZeL/cpeV3yL0xFcaXd98dl+0beBav8hi3EFzdNXDvtWEQbInHNxCJ4aTohmkPw0zG4isbw0kXurzVmLZMnRefjQR6Sl8eILeFzB65FcCYk=; 24:XqTZ1rEio3pvSzb7HT+/DUPRZlaObYAIzc6pl3ABsD4v3hLsd8DiPQ1Tnh4SGgmPi2ywx8X0IW1/jWrPXbmMW8QGhJHW4iCpxAGYxg4j2/g=; 7:eNfOXHyLsGVlcmN+POG/snXW8xukkBkUh07tovI6EAG45UF3xvLoDd0Q+IvU4dK6OEzM9Kp5YNgW3XgBe568zcNH5oU5RrrLwq0JZJPltYwOFAeAgezEihyuFVVOuj9fNMENm6idEPw5iWGy4r0u1hEbx0xx+X2ifvNmp5P7r2muJbNTnqiPIrWjhgV3hhH2dtO3iM80v70OyEBTwuFkefzCeprHi/7CKEv5N2vnhlk4YpefTBX4NiJotdypLmjG SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Dec 2017 06:56:48.4335 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 6e6135b8-aecc-4701-fc2f-08d54776d75d 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: CY1PR07MB2522 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: Quinn Tran FW has a finite number of IOCB resource. Driver will track it via the ql2xtrackfwres module parameter. User will be able to reserve X number of IOCBs for either the target path or initiator path. The left over IOCBs are shared between the 2 modes. The shared pool will be used 1st before tapping into the reserve pool. usage: modprobe qla2xxx ql2xtrackfwres=1 qlini_mode=dual echo 256 > /sys/class/scsi_host/hostX/device/reserve_ini_iocbs echo 256 > /sys/class/scsi_host/hostX/device/reserve_tgt_iocbs Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h | 50 +++++- drivers/scsi/qla2xxx/qla_dfs.c | 315 ++++++++++++++++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 36 +++++ drivers/scsi/qla2xxx/qla_inline.h | 102 ++++++++++++ drivers/scsi/qla2xxx/qla_iocb.c | 45 ++++++ drivers/scsi/qla2xxx/qla_isr.c | 10 +- drivers/scsi/qla2xxx/qla_os.c | 10 ++ drivers/scsi/qla2xxx/qla_target.c | 24 +++ drivers/scsi/qla2xxx/qla_target.h | 3 +- 10 files changed, 592 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 5e509763a419..8fbe1736a1a4 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -549,6 +549,12 @@ enum { TYPE_TGT_CMD, }; +struct iocb_resource { + u8 res_type; + u8 pad; + u16 iocb_cnt; +}; + typedef struct srb { /* * Do not move cmd_type field, it needs to @@ -556,6 +562,7 @@ typedef struct srb { */ uint8_t cmd_type; uint8_t pad[3]; + struct iocb_resource iores; atomic_t ref_count; wait_queue_head_t nvme_ls_waitq; struct fc_port *fcport; @@ -3396,6 +3403,7 @@ struct qla_qpair { uint32_t fw_started:1; uint32_t enable_class_2:1; uint32_t enable_explicit_conf:1; + uint32_t fw_res_tracking:1; uint32_t use_shadow_reg:1; uint16_t id; /* qp number used with FW */ @@ -3433,6 +3441,24 @@ struct scsi_qlt_host { struct qla_tgt *qla_tgt; }; +struct qla_fw_resources { + spinlock_t rescnt_lock; +#define DEF_RES_INI_IOCBS 256 +#define DEF_RES_TGT_IOCBS 256 +#define DEF_RES_BUSY_IOCBS 32 + u32 tgt_iocbs_reserve; + u32 ini_iocbs_reserve; + u32 busy_iocbs_reserve; + u32 tgt_iocbs_max; + u32 ini_iocbs_max; + u32 share_iocbs_max; + + /* these fields start high */ + atomic_t share_iocbs_used; + atomic_t tgt_iocbs_used; + atomic_t ini_iocbs_used; +}; + struct qlt_hw_data { /* Protected by hw lock */ uint32_t node_name_set:1; @@ -3461,6 +3487,9 @@ struct qlt_hw_data { struct dentry *dfs_tgt_sess; struct dentry *dfs_tgt_port_database; struct dentry *dfs_naqp; + struct dentry *dfs_ini_iocbs; + struct dentry *dfs_tgt_iocbs; + struct dentry *dfs_busy_iocbs; struct list_head q_full_list; uint32_t num_pend_cmds; @@ -3540,7 +3569,6 @@ struct qla_hw_data { uint32_t n2n_ae:1; uint32_t fw_started:1; uint32_t fw_init_done:1; - uint32_t detected_lr_sfp:1; uint32_t using_lr_setting:1; } flags; @@ -4103,6 +4131,7 @@ struct qla_hw_data { struct qlt_hw_data tgt; int allow_cna_fw_dump; + struct qla_fw_resources fwres; uint32_t fw_ability_mask; uint16_t min_link_speed; uint16_t max_speed_sup; @@ -4406,7 +4435,6 @@ struct qla2_sgx { #define QLA_QPAIR_MARK_NOT_BUSY(__qpair) \ atomic_dec(&__qpair->ref_count); \ - #define QLA_ENA_CONF(_ha) {\ int i;\ _ha->base_qpair->enable_explicit_conf = 1; \ @@ -4425,6 +4453,24 @@ struct qla2_sgx { } \ } +#define QLA_ENA_FW_RES_TRACKING(_ha) { \ + int i; \ + _ha->base_qpair->fw_res_tracking = 1; \ + for (i = 0; i < _ha->max_qpairs; i++) { \ + if (_ha->queue_pair_map[i]) \ + _ha->queue_pair_map[i]->fw_res_tracking = 1; \ + } \ +} + +#define QLA_DIS_FW_RES_TRACKING(_ha) { \ + int i; \ + _ha->base_qpair->fw_res_tracking = 0; \ + for (i = 0; i < _ha->max_qpairs; i++) { \ + if (_ha->queue_pair_map[i]) \ + _ha->queue_pair_map[i]->fw_res_tracking = 0; \ + } \ +} + /* * qla2x00 local function return status codes */ diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index d231e7156134..87a18a00d509 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -418,6 +418,278 @@ static const struct file_operations dfs_naqp_ops = { .write = qla_dfs_naqp_write, }; +static int +qla_dfs_ini_iocbs_show(struct seq_file *s, void *unused) +{ + struct scsi_qla_host *vha = s->private; + struct qla_hw_data *ha = vha->hw; + + if (!qla_dual_mode_enabled(vha)) { + seq_puts(s, + "This field requires Dual Mode to be enabled\n"); + return 0; + } + + seq_printf(s, "%d\n", ha->fwres.ini_iocbs_reserve); + + return 0; +} + +static int +qla_dfs_ini_iocbs_open(struct inode *inode, struct file *file) +{ + struct scsi_qla_host *vha = inode->i_private; + + return single_open(file, qla_dfs_ini_iocbs_show, vha); +} + +static ssize_t qla_dfs_ini_iocbs_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) +{ + struct seq_file *s = file->private_data; + struct scsi_qla_host *vha = s->private; + struct qla_hw_data *ha = vha->hw; + char *buf; + int rc = 0; + u32 v = 0; + + buf = memdup_user_nul(buffer, count); + if (IS_ERR(buf)) { + pr_err("host%ld: fail to copy user buffer", + vha->host_no); + return PTR_ERR(buf); + } + + rc = kstrtouint(buf, 0, &v); + if (rc < 0) { + ql_log(ql_log_info, vha, 0x707b, + "Unable to set initiator reserve iocbs\n"); + goto out_free; + } + + if (qla_dual_mode_enabled(vha)) { + if ((v < ha->orig_fw_iocb_count) && + (ha->fwres.ini_iocbs_reserve != v)) { + ha->fwres.ini_iocbs_reserve = v; + ql_log(ql_log_info, vha, 0x7024, + "Resetting. User change initiator reserve iocbs (%d/%d)\n", + v, ha->orig_fw_iocb_count); + + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + qla2x00_wait_for_chip_reset(vha); + } else { + ql_log(ql_log_warn, vha, 0x702e, + "Unable to set initiator reserve iocbs (%d/%d)\n", + v, ha->orig_fw_iocb_count); + } + } else { + if (v < (ha->orig_fw_iocb_count - ha->fwres.tgt_iocbs_reserve - + ha->fwres.busy_iocbs_reserve)) + ha->fwres.ini_iocbs_reserve = v; + else + ql_log(ql_log_warn, vha, 0x7039, + "Unable to set initiator reserve iocbs (%d/%d/%d/%d)\n", + v, ha->orig_fw_iocb_count, + ha->fwres.tgt_iocbs_reserve, + ha->fwres.busy_iocbs_reserve); + } + + rc = count; +out_free: + kfree(buf); + return rc; +} + +static const struct file_operations dfs_ini_iocbs_ops = { + .open = qla_dfs_ini_iocbs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = qla_dfs_ini_iocbs_write, +}; + + +static int +qla_dfs_tgt_iocbs_show(struct seq_file *s, void *unused) +{ + struct scsi_qla_host *vha = s->private; + struct qla_hw_data *ha = vha->hw; + + if (!qla_dual_mode_enabled(vha)) { + seq_puts(s, + "This field requires Dual Mode to be enabled\n"); + return 0; + } + + seq_printf(s, "%d\n", ha->fwres.tgt_iocbs_reserve); + + return 0; +} + +static int +qla_dfs_tgt_iocbs_open(struct inode *inode, struct file *file) +{ + struct scsi_qla_host *vha = inode->i_private; + + return single_open(file, qla_dfs_tgt_iocbs_show, vha); +} + +static ssize_t +qla_dfs_tgt_iocbs_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + struct seq_file *s = file->private_data; + struct scsi_qla_host *vha = s->private; + struct qla_hw_data *ha = vha->hw; + char *buf; + int rc = 0; + u32 v = 0; + + buf = memdup_user_nul(buffer, count); + if (IS_ERR(buf)) { + pr_err("host%ld: fail to copy user buffer.", + vha->host_no); + return PTR_ERR(buf); + } + rc = kstrtouint(buf, 0, &v); + if (rc < 0) { + ql_log(ql_log_info, vha, 0x70a5, + "Unable to set initiator reserve iocbs.\n"); + goto out_free; + } + + if (qla_dual_mode_enabled(vha)) { + if ((v < ha->orig_fw_iocb_count) && + (ha->fwres.ini_iocbs_reserve != v)) { + ha->fwres.ini_iocbs_reserve = v; + ql_log(ql_log_info, vha, 0x703b, + "Resetting. User changed target reserve iocbs (%d/%d).\n", + v, ha->orig_fw_iocb_count); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + qla2x00_wait_for_chip_reset(vha); + } else + ql_log(ql_log_warn, vha, 0x7045, + "Unable to set target reserve iocbs (%d/%d).\n", + v, ha->orig_fw_iocb_count); + } else { + if (v < (ha->orig_fw_iocb_count - ha->fwres.ini_iocbs_reserve - + ha->fwres.busy_iocbs_reserve)) + ha->fwres.tgt_iocbs_reserve = v; + else + ql_log(ql_log_warn, vha, 0x7047, + "Unable to set target reserve iocbs (%d/%d/%d/%d).\n", + v, ha->orig_fw_iocb_count, + ha->fwres.ini_iocbs_reserve, + ha->fwres.busy_iocbs_reserve); + } + + rc = count; +out_free: + kfree(buf); + return rc; +} + +static const struct file_operations dfs_tgt_iocbs_ops = { + .open = qla_dfs_tgt_iocbs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = qla_dfs_tgt_iocbs_write, +}; + +static int +qla_dfs_busy_iocbs_show(struct seq_file *s, void *unused) +{ + struct scsi_qla_host *vha = s->private; + struct qla_hw_data *ha = vha->hw; + + if (!qla_dual_mode_enabled(vha)) { + seq_puts(s, + "This field requires Dual Mode to be enabled\n"); + return 0; + } + + seq_printf(s, "%d\n", ha->fwres.busy_iocbs_reserve); + + return 0; +} + +static int +qla_dfs_busy_iocbs_open(struct inode *inode, struct file *file) +{ + struct scsi_qla_host *vha = inode->i_private; + + return single_open(file, qla_dfs_busy_iocbs_show, vha); +} + +static ssize_t +qla_dfs_busy_iocbs_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + struct seq_file *s = file->private_data; + struct scsi_qla_host *vha = s->private; + struct qla_hw_data *ha = vha->hw; + char *buf; + int rc = 0; + u32 v = 0; + + buf = memdup_user_nul(buffer, count); + if (IS_ERR(buf)) { + pr_err("host%ld: fail to copy user buffer.", + vha->host_no); + return PTR_ERR(buf); + } + + rc = kstrtouint(buf, 0, &v); + if (rc < 0) { + ql_log(ql_log_info, vha, 0x70a6, + "Unable to set initiator reserve iocbs.\n"); + goto out_free; + } + + if (qla_dual_mode_enabled(vha)) { + if ((v < ha->orig_fw_iocb_count) && + (ha->fwres.busy_iocbs_reserve != v)) { + ha->fwres.busy_iocbs_reserve = v; + ql_log(ql_log_info, vha, 0x7073, + "Resetting. User change Busy reserve iocbs (%d/%d).\n", + v, ha->orig_fw_iocb_count); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + qla2x00_wait_for_chip_reset(vha); + } else { + ql_log(ql_log_warn, vha, 0x7074, + "Unable to set busy reserve iocbs (%d/%d).\n", + v, ha->orig_fw_iocb_count); + } + } else { + if (v < (ha->orig_fw_iocb_count - ha->fwres.ini_iocbs_reserve - + ha->fwres.tgt_iocbs_reserve)) + ha->fwres.busy_iocbs_reserve = v; + else + ql_log(ql_log_warn, vha, 0x7075, + "Unable to set busy reserve iocbs (%d/%d/%d/%d).\n", + v, ha->orig_fw_iocb_count, + ha->fwres.ini_iocbs_reserve, + ha->fwres.tgt_iocbs_reserve); + } + + rc = count; +out_free: + kfree(buf); + return rc; +} + +static const struct file_operations dfs_busy_iocbs_ops = { + .open = qla_dfs_busy_iocbs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = qla_dfs_busy_iocbs_write, +}; + int qla2x00_dfs_setup(scsi_qla_host_t *vha) @@ -504,6 +776,33 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha) "Unable to create debugFS naqp node.\n"); goto out; } + + if (ql2xtrackfwres) { + ha->tgt.dfs_ini_iocbs = + debugfs_create_file("reserve_ini_iocbs", + 0400, ha->dfs_dir, vha, &dfs_ini_iocbs_ops); + if (!ha->tgt.dfs_ini_iocbs) { + ql_log(ql_log_warn, vha, 0xd011, + "Unable to create debugFS reserve_ini_iocbs node.\n"); + goto out; + } + ha->tgt.dfs_tgt_iocbs = + debugfs_create_file("reserve_tgt_iocbs", + 0400, ha->dfs_dir, vha, &dfs_tgt_iocbs_ops); + if (!ha->tgt.dfs_tgt_iocbs) { + ql_log(ql_log_warn, vha, 0xd011, + "Unable to create debugFS reserve_tgt_iocbs node.\n"); + goto out; + } + ha->tgt.dfs_busy_iocbs = + debugfs_create_file("reserve_busy_iocbs", + 0400, ha->dfs_dir, vha, &dfs_busy_iocbs_ops); + if (!ha->tgt.dfs_busy_iocbs) { + ql_log(ql_log_warn, vha, 0xd011, + "Unable to create debugFS reserve_busy_iocbs node.\n"); + goto out; + } + } } out: return 0; @@ -514,6 +813,22 @@ qla2x00_dfs_remove(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + + if (ha->tgt.dfs_ini_iocbs) { + debugfs_remove(ha->tgt.dfs_ini_iocbs); + ha->tgt.dfs_ini_iocbs = NULL; + } + + if (ha->tgt.dfs_tgt_iocbs) { + debugfs_remove(ha->tgt.dfs_tgt_iocbs); + ha->tgt.dfs_tgt_iocbs = NULL; + } + + if (ha->tgt.dfs_busy_iocbs) { + debugfs_remove(ha->tgt.dfs_busy_iocbs); + ha->tgt.dfs_busy_iocbs = NULL; + } + if (ha->tgt.dfs_naqp) { debugfs_remove(ha->tgt.dfs_naqp); ha->tgt.dfs_naqp = NULL; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index bf907386f177..66dcbdb91244 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -148,6 +148,7 @@ extern int ql2xuctrlirq; extern int ql2xnvmeenable; extern int ql2xautodetectsfp; extern int ql2xenablemsix; +extern int ql2xtrackfwres; extern int qla2x00_loop_reset(scsi_qla_host_t *); extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 24d0f9d419d2..429305caef47 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3108,6 +3108,42 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) MIN_MULTI_ID_FABRIC - 1; } qla2x00_get_resource_cnts(vha); + if (ql2xtrackfwres) { + if (qla_dual_mode_enabled(vha)) { + ha->fwres.tgt_iocbs_max = + ha->orig_fw_iocb_count - + ha->fwres.ini_iocbs_reserve - + ha->fwres.busy_iocbs_reserve; + ha->fwres.ini_iocbs_max = + ha->orig_fw_iocb_count - + ha->fwres.tgt_iocbs_reserve - + ha->fwres.busy_iocbs_reserve; + ha->fwres.share_iocbs_max = + ha->orig_fw_iocb_count - + ha->fwres.ini_iocbs_reserve - + ha->fwres.tgt_iocbs_reserve - + ha->fwres.busy_iocbs_reserve; + + } else if (qla_tgt_mode_enabled(vha)) { + ha->fwres.tgt_iocbs_max = + ha->orig_fw_iocb_count - + ha->fwres.busy_iocbs_reserve; + ha->fwres.ini_iocbs_max = 0; + ha->fwres.share_iocbs_max = + ha->orig_fw_iocb_count - + ha->fwres.ini_iocbs_reserve - + ha->fwres.tgt_iocbs_reserve - + ha->fwres.busy_iocbs_reserve; + } else + QLA_DIS_FW_RES_TRACKING(ha); + + atomic_set(&ha->fwres.ini_iocbs_used, + ha->fwres.ini_iocbs_max); + atomic_set(&ha->fwres.tgt_iocbs_used, + ha->fwres.tgt_iocbs_max); + atomic_set(&ha->fwres.share_iocbs_used, + ha->fwres.share_iocbs_max); + } /* * Allocate the array of outstanding commands diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 4d32426393c7..d8dc6dea1525 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -221,6 +221,7 @@ qla2xxx_get_qpair_sp(struct qla_qpair *qpair, fc_port_t *fcport, gfp_t flag) sp->fcport = fcport; sp->iocbs = 1; sp->vha = qpair->vha; + sp->qpair = qpair; done: if (!sp) QLA_QPAIR_MARK_NOT_BUSY(qpair); @@ -253,6 +254,7 @@ qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag) sp->cmd_type = TYPE_SRB; sp->iocbs = 1; sp->vha = vha; + sp->qpair = vha->hw->base_qpair; done: if (!sp) QLA_VHA_MARK_NOT_BUSY(vha); @@ -366,3 +368,103 @@ qla_83xx_start_iocbs(struct qla_qpair *qpair) WRT_REG_DWORD(req->req_q_in, req->ring_index); } + +enum { + RESOURCE_NONE, + RESOURCE_INI, + RESOURCE_TGT, + RESOURCE_SHR, +}; + +static inline int +qla_get_iocbs(struct qla_hw_data *ha, struct iocb_resource *iores) +{ + unsigned long flags; + + switch (iores->res_type) { + case RESOURCE_TGT: + /* spin lock is required here because atomic lib is unable + * to do "check 1st and sub" under 1 atomic operaton. + */ + spin_lock_irqsave(&ha->fwres.rescnt_lock, flags); + if (atomic_read(&ha->fwres.share_iocbs_used) < + iores->iocb_cnt) { + /* share pool is emptied */ + if (atomic_read(&ha->fwres.tgt_iocbs_used) < + iores->iocb_cnt) { + iores->res_type = RESOURCE_NONE; + spin_unlock_irqrestore(&ha->fwres.rescnt_lock, + flags); + return -EAGAIN; + } + + atomic_sub(iores->iocb_cnt, &ha->fwres.tgt_iocbs_used); + iores->res_type = RESOURCE_TGT; + spin_unlock_irqrestore(&ha->fwres.rescnt_lock, flags); + return 0; + } + + atomic_sub(iores->iocb_cnt, &ha->fwres.share_iocbs_used); + iores->res_type = RESOURCE_SHR; + spin_unlock_irqrestore(&ha->fwres.rescnt_lock, flags); + + return 0; + + case RESOURCE_INI: + spin_lock_irqsave(&ha->fwres.rescnt_lock, flags); + if (atomic_read(&ha->fwres.share_iocbs_used) < + iores->iocb_cnt) { + if (atomic_read(&ha->fwres.ini_iocbs_used) < + iores->iocb_cnt) { + /* fail to get resource */ + iores->res_type = RESOURCE_NONE; + spin_unlock_irqrestore(&ha->fwres.rescnt_lock, + flags); + return -EAGAIN; + } else { + atomic_sub(iores->iocb_cnt, + &ha->fwres.ini_iocbs_used); + iores->res_type = RESOURCE_INI; + spin_unlock_irqrestore(&ha->fwres.rescnt_lock, + flags); + return 0; + } + } + atomic_sub(iores->iocb_cnt, &ha->fwres.share_iocbs_used); + iores->res_type = RESOURCE_SHR; + spin_unlock_irqrestore(&ha->fwres.rescnt_lock, flags); + return 0; + + default: + break; + } + + return -EIO; +} + +static inline void +qla_put_iocbs(struct qla_qpair *qpair, struct iocb_resource *iores) +{ + struct scsi_qla_host *vha; + + if (!qpair || !qpair->fw_res_tracking) + return; + + vha = qpair->vha; + + switch (iores->res_type) { + case RESOURCE_TGT: + atomic_add(iores->iocb_cnt, &vha->hw->fwres.tgt_iocbs_used); + break; + case RESOURCE_INI: + atomic_add(iores->iocb_cnt, &vha->hw->fwres.ini_iocbs_used); + break; + case RESOURCE_SHR: + atomic_add(iores->iocb_cnt, &vha->hw->fwres.share_iocbs_used); + break; + default: + break; + } + + iores->res_type = RESOURCE_NONE; +} diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 62b3d0a8a961..417c40f21244 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1460,6 +1460,14 @@ qla24xx_start_scsi(srb_t *sp) tot_dsds = nseg; req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); + + if (ha->base_qpair->fw_res_tracking) { + sp->iores.iocb_cnt = req_cnt; + sp->iores.res_type = RESOURCE_INI; + if (qla_get_iocbs(ha, &sp->iores)) + goto queuing_error; + } + if (req->cnt < (req_cnt + 2)) { cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : RD_REG_DWORD_RELAXED(req->req_q_out); @@ -1538,6 +1546,7 @@ qla24xx_start_scsi(srb_t *sp) if (tot_dsds) scsi_dma_unmap(cmd); + qla_put_iocbs(ha->base_qpair, &sp->iores); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_FUNCTION_FAILED; @@ -1661,6 +1670,13 @@ qla24xx_dif_start_scsi(srb_t *sp) /* Total Data and protection sg segment(s) */ tot_prot_dsds = nseg; tot_dsds += nseg; + if (ha->base_qpair->fw_res_tracking) { + sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds); + sp->iores.res_type = RESOURCE_INI; + if (qla_get_iocbs(ha, &sp->iores)) + goto queuing_error; + } + if (req->cnt < (req_cnt + 2)) { cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : RD_REG_DWORD_RELAXED(req->req_q_out); @@ -1739,6 +1755,7 @@ qla24xx_dif_start_scsi(srb_t *sp) req->outstanding_cmds[handle] = NULL; req->cnt += req_cnt; } + qla_put_iocbs(ha->base_qpair, &sp->iores); /* Cleanup will be performed by the caller (queuecommand) */ spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -1813,6 +1830,13 @@ qla2xxx_start_scsi_mq(srb_t *sp) tot_dsds = nseg; req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); + if (qpair->fw_res_tracking) { + sp->iores.iocb_cnt = req_cnt; + sp->iores.res_type = RESOURCE_INI; + if (qla_get_iocbs(ha, &sp->iores)) + goto queuing_error; + } + if (req->cnt < (req_cnt + 2)) { cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : RD_REG_DWORD_RELAXED(req->req_q_out); @@ -1890,6 +1914,7 @@ qla2xxx_start_scsi_mq(srb_t *sp) if (tot_dsds) scsi_dma_unmap(cmd); + qla_put_iocbs(qpair, &sp->iores); spin_unlock_irqrestore(&qpair->qp_lock, flags); return QLA_FUNCTION_FAILED; @@ -2028,6 +2053,14 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) /* Total Data and protection sg segment(s) */ tot_prot_dsds = nseg; tot_dsds += nseg; + + if (qpair->fw_res_tracking) { + sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds); + sp->iores.res_type = RESOURCE_INI; + if (qla_get_iocbs(ha, &sp->iores)) + goto queuing_error; + } + if (req->cnt < (req_cnt + 2)) { cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : RD_REG_DWORD_RELAXED(req->req_q_out); @@ -2103,6 +2136,7 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) req->outstanding_cmds[handle] = NULL; req->cnt += req_cnt; } + qla_put_iocbs(qpair, &sp->iores); /* Cleanup will be performed by the caller (queuecommand) */ spin_unlock_irqrestore(&qpair->qp_lock, flags); @@ -3625,6 +3659,14 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) /* Calculate number of IOCB required */ req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); + if (ha->base_qpair->fw_res_tracking) { + sp->iores.iocb_cnt = req_cnt; + sp->iores.res_type = RESOURCE_INI; + if (qla_get_iocbs(ha, &sp->iores)) { + rval = EXT_STATUS_BUSY; + goto queuing_error; + } + } /* Check for room on request queue. */ if (req->cnt < req_cnt + 2) { @@ -3667,6 +3709,9 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) wmb(); qla2x00_start_iocbs(vha, req); queuing_error: + if (rval) + qla_put_iocbs(ha->base_qpair, &sp->iores); + spin_unlock_irqrestore(&ha->hardware_lock, flags); return rval; } diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 33865e0bb29f..7ae8d4d22952 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1283,6 +1283,8 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha, /* Free outstanding command slot. */ req->outstanding_cmds[index] = NULL; + qla_put_iocbs(sp->qpair, &sp->iores); + /* Save ISP completion status */ sp->done(sp, DID_OK << 16); } else { @@ -2368,6 +2370,9 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, bsg_job->reply_len = sizeof(struct fc_bsg_reply); /* Always return DID_OK, bsg will send the vendor specific response * in this case only */ + + qla_put_iocbs(sp->qpair, &sp->iores); + sp->done(sp, DID_OK << 6); } @@ -2745,8 +2750,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) cp->cmnd, scsi_bufflen(cp), rsp_info_len, resid_len, fw_resid_len, sp, cp); - if (rsp->status_srb == NULL) + if (rsp->status_srb == NULL) { + qla_put_iocbs(sp->qpair, &sp->iores); sp->done(sp, res); + } } /** @@ -2849,6 +2856,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) case MBX_IOCB_TYPE: sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); if (sp) { + qla_put_iocbs(sp->qpair, &sp->iores); sp->done(sp, res); return 0; } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 029b95b2bd8a..7f361e93c593 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -277,6 +277,11 @@ MODULE_PARM_DESC(ql2xenablemsix, " 1 -- enable MSI-X interrupt mechanism.\n" " 2 -- enable MSI interrupt mechanism.\n"); +int ql2xtrackfwres; +module_param(ql2xtrackfwres, int, 0444); +MODULE_PARM_DESC(ql2xtrackfwres, + "Track FW resource. 0(default): disabled"); + /* * SCSI host template entry points */ @@ -1772,6 +1777,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) atomic_dec( &sp->ref_count); } + qla_put_iocbs(sp->qpair, &sp->iores); sp->done(sp, res); } else { if (!vha->hw->tgt.tgt_ops || !tgt || @@ -2790,6 +2796,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->link_data_rate = PORT_SPEED_UNKNOWN; ha->optrom_size = OPTROM_SIZE_2300; ha->max_exchg = FW_MAX_EXCHANGES_CNT; + ha->fwres.ini_iocbs_reserve = DEF_RES_INI_IOCBS; + ha->fwres.tgt_iocbs_reserve = DEF_RES_TGT_IOCBS; + ha->fwres.busy_iocbs_reserve = DEF_RES_BUSY_IOCBS; + spin_lock_init(&ha->fwres.rescnt_lock); /* Assign ISP specific operations. */ if (IS_QLA2100(ha)) { diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index fcfdbe1420cd..0d77b2f67077 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2628,6 +2628,14 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd, } } + if (cmd->qpair->fw_res_tracking) { + cmd->iores.iocb_cnt = *full_req_cnt; + cmd->iores.res_type = RESOURCE_TGT; + if (qla_get_iocbs(cmd->vha->hw, &cmd->iores)) { + qlt_unmap_sg(cmd->vha, cmd); + return -EAGAIN; + } + } return 0; } @@ -3202,6 +3210,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, out_unmap_unlock: qlt_unmap_sg(vha, cmd); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + qla_put_iocbs(qpair, &cmd->iores); return res; } @@ -3243,6 +3252,14 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) } spin_lock_irqsave(qpair->qp_lock_ptr, flags); + + if (cmd->qpair->fw_res_tracking) { + cmd->iores.iocb_cnt = prm.req_cnt; + cmd->iores.res_type = RESOURCE_TGT; + if (qla_get_iocbs(cmd->vha->hw, &cmd->iores)) + goto out_unlock_free_unmap; + } + /* Does F/W have an IOCBs for this request */ res = qlt_check_reserve_free_req(qpair, prm.req_cnt); if (res != 0) @@ -3281,6 +3298,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) qlt_unmap_sg(vha, cmd); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + qla_put_iocbs(qpair, &cmd->iores); return res; } EXPORT_SYMBOL(qlt_rdy_to_xfer); @@ -3810,6 +3828,8 @@ qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd) dump_stack(); } + qla_put_iocbs(cmd->qpair, &cmd->iores); + cmd->trc_flags |= TRC_FLUSH; ha->tgt.tgt_ops->free_cmd(cmd); } @@ -3841,6 +3861,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, se_cmd = &cmd->se_cmd; cmd->cmd_sent_to_fw = 0; + qla_put_iocbs(cmd->qpair, &cmd->iores); qlt_unmap_sg(vha, cmd); @@ -6412,6 +6433,9 @@ qlt_enable_vha(struct scsi_qla_host *vha) qla24xx_disable_vp(vha); qla24xx_enable_vp(vha); } else { + if (ql2xtrackfwres && (IS_QLA83XX(ha) || IS_QLA27XX(ha))) + QLA_ENA_FW_RES_TRACKING(ha); + set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); qla2xxx_wake_dpc(base_vha); qla2x00_wait_for_hba_online(base_vha); diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index aba58d3848a6..588c8bcf1192 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -877,7 +877,8 @@ struct qla_tgt_cmd { * Do not move cmd_type field. it needs to line up with srb->cmd_type */ uint8_t cmd_type; - uint8_t pad[7]; + uint8_t pad[3]; + struct iocb_resource iores; struct se_cmd se_cmd; struct fc_port *sess; struct qla_qpair *qpair;