From patchwork Fri Dec 7 22:28:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Don Brace X-Patchwork-Id: 10718945 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 5133C109C for ; Fri, 7 Dec 2018 22:28:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3D9372DA7C for ; Fri, 7 Dec 2018 22:28:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 307312F73E; Fri, 7 Dec 2018 22:28:24 +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,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 298E52DA7C for ; Fri, 7 Dec 2018 22:28:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726076AbeLGW2W (ORCPT ); Fri, 7 Dec 2018 17:28:22 -0500 Received: from mail-eopbgr740048.outbound.protection.outlook.com ([40.107.74.48]:56192 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726008AbeLGW2W (ORCPT ); Fri, 7 Dec 2018 17:28:22 -0500 Received: from MWHPR19CA0067.namprd19.prod.outlook.com (2603:10b6:300:94::29) by CY4PR19MB0935.namprd19.prod.outlook.com (2603:10b6:903:a9::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1404.20; Fri, 7 Dec 2018 22:28:12 +0000 Received: from BY2FFO11FD019.protection.gbl (2a01:111:f400:7c0c::185) by MWHPR19CA0067.outlook.office365.com (2603:10b6:300:94::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1404.19 via Frontend Transport; Fri, 7 Dec 2018 22:28:12 +0000 Authentication-Results: spf=pass (sender IP is 208.19.99.221) smtp.mailfrom=microsemi.com; linux.vnet.ibm.com; dkim=none (message not signed) header.d=none;linux.vnet.ibm.com; dmarc=bestguesspass action=none header.from=microsemi.com; Received-SPF: Pass (protection.outlook.com: domain of microsemi.com designates 208.19.99.221 as permitted sender) receiver=protection.outlook.com; client-ip=208.19.99.221; helo=AUSMBX1.microsemi.net; Received: from AUSMBX1.microsemi.net (208.19.99.221) by BY2FFO11FD019.mail.protection.outlook.com (10.1.14.107) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.1404.13 via Frontend Transport; Fri, 7 Dec 2018 22:28:12 +0000 Received: from AUSMBX2.microsemi.net (10.201.34.32) by AUSMBX1.microsemi.net (10.201.34.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1531.3; Fri, 7 Dec 2018 16:28:11 -0600 Received: from [127.0.1.1] (10.238.32.34) by ausmbx2.microsemi.net (10.201.34.32) with Microsoft SMTP Server id 15.1.1531.3 via Frontend Transport; Fri, 7 Dec 2018 16:28:10 -0600 Subject: [PATCH 01/20] smartpqi: add support for PQI Config Table handshake From: Don Brace To: , , , , , , , , , , , CC: Date: Fri, 7 Dec 2018 16:28:10 -0600 Message-ID: <154422169082.1218.12309135947267907976.stgit@brunhilda> In-Reply-To: <154422079293.1218.12539829857034151457.stgit@brunhilda> References: <154422079293.1218.12539829857034151457.stgit@brunhilda> User-Agent: StGit/0.19-dirty MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:208.19.99.221;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(7916004)(346002)(136003)(39860400002)(396003)(376002)(2980300002)(199004)(189003)(356004)(50466002)(4744004)(8936002)(8676002)(110136005)(16576012)(316002)(81166006)(53936002)(44832011)(58126008)(230700001)(81156014)(486006)(478600001)(2201001)(14444005)(446003)(575784001)(476003)(126002)(86362001)(106002)(11346002)(33716001)(106466001)(305945005)(77096007)(26005)(186003)(69596002)(103116003)(2906002)(4326008)(5660300001)(9686003)(33896004)(47776003)(336012)(97736004)(68736007)(23676004)(2486003)(76176011)(921003)(1121003)(83996005)(2101003);DIR:OUT;SFP:1101;SCL:1;SRVR:CY4PR19MB0935;H:AUSMBX1.microsemi.net;FPR:;SPF:Pass;LANG:en;PTR:InfoDomainNonexistent;A:1;MX:1; X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11FD019;1:otHtHh4vUn1mWs1u1DRBHPgEh+M65i3MXBkG1e7Mc/d5xCtKgF9jphdz2QF0uEjrPD5uIw5PbKaw8kXzrDRduYSAFoLB2EBBZUeCHrUqH0Tfc/t3TknpYZwg+0sd//ot X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 515a730e-ce8f-4801-1bb1-08d65c934601 X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:(2390098)(7020095)(4652040)(8989299)(5600074)(711020)(4608076)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(2017052603328)(7153060);SRVR:CY4PR19MB0935; X-Microsoft-Exchange-Diagnostics: 1;CY4PR19MB0935;3:cGGMuXW15cOfF1yNdfz9G7t3dwMzT/DxSvU4R09tqj8tOCJBD8qhGoedtaRk8YaBHWnzha4+erBhQauM3X3eSc5064oUpWMCXlc3bD2xmlnjjSd7SZVjsPhG4Wu//iOEPAghsCdk+PAXGFmTWqd0z/rxqxk/0CXVMZam1RfEOldI6+QGkWp4cQqa3ILbIpyvlLalf6NG/ma9uTcjBfSrZ9JiX+SoMl/Ht7aa2ob+Q3IUhZH59sAVW+jOJQRVFLCLpwX9JRAVDSuwNPOT/tx73DCFj93aoUw1R0olHoVto5/lvtyBRXSOo5iNvWnYpNSlMv6ttuxWkeMuOsR29rg5ukMHYGQz0g6im6Jj5/Qf3wo=;25:WhI25lkUjYLnP1wLgjE3+h5/YRofUJziQXPmD0lvvOapEz5lOoZ8oljpbAwnNt9HxjS4ZfBQDQQW41KrWSR1aH5eGjKDaLS05Dqa3SZKEKwSLW6yIFAbzT0p5lIua8GGcTUF/my0gMBiHK614IZ5XV7OyMiNfpjYdqATIiJn/fc7YpHn9JbI7ZsldlI1t7I4L/B02dp6DJrt1Rjnav4AAr2gALSWOgQwC7zqKKVSXsuLUr2wHCdGb53VQ43E/9PVoyiRKTlxfdD9VrRo0R7/y4kHFnzm502udexfBwX0uUkiBvFXTtSthTdaAw4mmAZsB0A0ZHSrFCUtdeP89hWkgQ== X-MS-TrafficTypeDiagnostic: CY4PR19MB0935: X-Microsoft-Exchange-Diagnostics: 1;CY4PR19MB0935;31:Xqrycf0vVi9eSLXCZyZsX7vFqB0j6dy8n8exGTqgLEdSpU8XmZaqrUHFXqKy98uxVoeZjftYGP1ip7Q2HqhNYK9EoeX0p2Fz07meom3rjc2OWV8F98b2Z8IMrvMuTdLUgZL0ZXh/Yf5eMRFebSk/F42+kckAzcmoxushH57x42aJ1RNEcEfZWfkXxpPp1LVVq9loBZEqnB7EqtvdGWwRFHnBPRB2NPZ/9ZE09buke5k=;20:A/jmuk4KAMYa+K6SpsYt0/argYTTnNSniv1j0+79mHiGrwH/tu4I81Sq0qoRO0hOVfqaHRHgtWgSjx2HyH3WLdOEkAj65Umb4bpsvr24UoXXTqtCzb1IIPZw6AcfvjQXLqPteVLitTlF7e6I5BNU/ylUGN3odmQCjHb9IdqlVw8QTTfU4AlraenRKO5JES/dD4yY/RSeDrZRvlWS2SBoYd/FOIYsIBZKUmoyTendTXWrAnxmcQ3iz+mvuHTgmehzPtRkJdT2Hhoh/NSIQxb5ajkJxfKVu9tsni1f75+QYQSjI4Fxao6Y0Y7FtXMbF9WZ8akluPY0r0BkV/KL0PFqf/GIr1eGZKvgaCQgXSWAagpZi4DBe4LbshDfYU1jsuCtMxAtw2dHH5MZDGVQyDN6D130cx4Yx3xGp/k+QjlCPS35dTEr54C0pkj5GEYAR9xdWPjOBf6wtIivkUnI7JfwObVdbjdjHcTsE1n9PohEMJ+YAutFLrTX8SSTI13cY1id X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(8211001083)(6040522)(2401047)(5005006)(8121501046)(3231455)(999002)(944501520)(52105112)(93006095)(93004095)(3002001)(10201501046)(6055026)(148016)(149066)(150057)(6041310)(20161123564045)(20161123560045)(20161123558120)(20161123562045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(201708071742011)(7699051)(76991095);SRVR:CY4PR19MB0935;BCL:0;PCL:0;RULEID:;SRVR:CY4PR19MB0935; X-Microsoft-Exchange-Diagnostics: 1;CY4PR19MB0935;4:CYetOXFftFcvw+P4N+e7u0BNTHi7pr4QA8XZ2EZ3cmjK5BT/eJHMtPU9Rr/xSOeab/BspiMFfCiHcVb2r9ZEun366CL/mOdhlDzbBmFMfiTq4+bzSiHdGBqC0oODpDNj6DABdpx9QRxptOBgocxITDrg3txv/hswQzivEfjfYQbOGQ6AOHkQBqApPOfhbuTihFBs08uKRPnXT+2GLD6BTXbAit+xwaFUHzRLOqPMJBybTazfalyTLZ4lhSTpY/jGmkJkvk2afB0nC91UJM3b0Q== X-Forefront-PRVS: 0879599414 X-Microsoft-Exchange-Diagnostics: =?utf-8?q?1=3BCY4PR19MB0935=3B23=3AQ0EP2Hm?= =?utf-8?q?XT5HCTcFrzZK9Hk20QECejDHV3F4rocCS746iqrWIP/QU9XAAEyXya+pD+KYpUTd+?= =?utf-8?q?dTvKlJjhqNnNB9bjAzHZpzkRCog7ORivDKeI4R7yRo818Hq1S6myyJscnhcNjN6H3?= =?utf-8?q?90Jk3McHoEkxrjhoLzNEf4oDD1DAqm0qJlLYt7q2oGkneURfTLNwxhzOzuMZQPjSQ?= =?utf-8?q?CPejIIpuboJODPOIA1Df5L6nohRRhdtc1nQxOUTrf1dzT4SiEVInLZDnNiJwtTMBE?= =?utf-8?q?oZFNQJ1jg9XisMpkYwqNxitaxXI1C4KyMk+kbkc9+B19+XiKoH5yjadEVmqDjp7Dh?= =?utf-8?q?/3un1Tn97SqJJMYnw1ixiz7vX0grnMl/Vmrg3YZtE4n/qX838JyyhFT7+HZ9bOM1L?= =?utf-8?q?uOwNUzts26Cd0YmNRM1WVZExGT5bkdaioLPRPFgK/E1UyGxkgOJp0YNBC7jH87YkE?= =?utf-8?q?RTyvxzGF1reDnsifE4yhs0A1cEOq9F+4QOmqJ55kzG4/A2B+gnseKyAU6Onb5+QHO?= =?utf-8?q?gd/5+TtfeV6Zajh3yvcFwN/cQH0LsJ1Oq+lL/ZzKi19j3Q2rhn62Qc4+efpWvVP8H?= =?utf-8?q?nNr35Hj5rogQZHyjcxfC4GLqGnGQDYJAbzmyCcxc0QkkQ7uKKtp6VzhSLIH/UmH1a?= =?utf-8?q?F2fCP6Ub7DFmprGIYcj2A1DdSCFyzqLYTyL6OCVpn6a/whYNkuGUM5R7A5ozmp2cn?= =?utf-8?q?ecwwTeW7/XnpX9cOPqP1Rp+54kKmKu3extwcMfEkiufv3flnbNz9BaFHiGkpZTMSS?= =?utf-8?q?KSfkD7IzC42ArRsx/o7FTu6yBEDcRqf7udfmPONxGVx2sVHSf/GHweGg4EttmPJ9F?= =?utf-8?q?sbeXzCUXhlVowm508N3liwijnzLLqHUbROxOMbrt1tTXVUC323UC7p8hNS5AJYAKe?= =?utf-8?q?rkVaW0KzyEvf1H5TsbOe8I3wlpK7J18QpXJt0e5rrKFDlalWs1W6R8k7DoWKM7+uW?= =?utf-8?q?j0PsCbm/li9ljn4KwdVfCr1E0PFWXwGctR+FuJm48C7QvYy26jVS3t0XAYaDxASq0?= =?utf-8?q?ErBBKiiLjMzyP1FAk96YI5XVoBGv/twJD7TdIkyfBNpMuTwmkaZgKapeho9Vhl85E?= =?utf-8?q?C/mr6jkOkP3ipnYAZ1V97EevKriZm1ocMvFfCFVEuaEi5By0JDkCPGmTLgawANW0V?= =?utf-8?q?fcgs3BGbOtWSwsg0tujI+DypCP2udDAOmp+YzCNWi6wBJ/CpogSQZqSqdrRcXnCBf?= =?utf-8?q?DiCwD7Bn4Ma8c2IFYjLfMOMIMJH5gj+Pz1n0C0?= X-Microsoft-Antispam-Message-Info: ak9kCKN8nleb9w8tNj+VqwnbmlQJpn+gsHPQVHfYUV+FVFr+PiVjmklNrfyfC8QbqhrV5viwd4gE9K+IDYKFYRifUYiXGQEKbBHrx1t8KJ6cY5j6/agffZZxBH5H7Orp7oO59My56al4mFjeh+VWWIGxgxCBDxMG5fZLoZ/JolH/9q+9Zo2biVN6+n5mx5yjBBqGmyeYIMSGJMtKDh/OCA5Zqs4rvlJIUseXiQg/jghXoYtxqA1yn2urlE7oVulI54eeIfXiKoDvMA1IGSNwPZ2Vjion1M8KBBXW1Ed1c5lPptbwIvyZX/ZLfLO+aPTae/l63biyTINd+t86IoHzTLBp7EZxRWMFZfS9EPYmX8Q= X-Microsoft-Exchange-Diagnostics: 1;CY4PR19MB0935;6:5WlHVjasCKyPyme4MtUOafL94dqRVOxlBe5RXgUvpPMwM6qn/VeExEQNdrRerKVTNxxOkMQvi20hF5XuenNk5OUrlnFORpnO3XAp3DDSVjwwpZjACJzsYDMYlXPW/EQzYClPcSIlz9/Bs8vKEkTNZg18uMt2QbylzhVXbTfKzRNMdiAy0t3sLm0ZPANlQBazjwpdSft53rSFtUhUnD3dyF112N2PJTIFW+gtt53rG33L0w+plCtQtW0p+YAJMNnIwZh7N4qV8n/nI+3rufVi6x/XMd+52ZupgjYO9O+26jMOCiOJP82a6zG7U66X2i+HeNZ3IdpBiZGT+YogAjVL3jucTWKmPhcVFJqie4KBUJoqMfqo/Dp983PnxN6FT8PPSeGn6irjbDwv3KFu8psFyyE/8lkHUTSGEp2ZRnlzd485dGj39gdmyP5q7MJLckWiY3e3EegtLHfZdu5kw8ihPw==;5:fdVmnaDfdTtLWeF7pf5srfGLcIalaAhQ80+ZcqAgyq+gWa3xejWIOiD6e3LYcc8WSygl1ZEzF7nrkTcMZGyYtzDf3QlkAi3erUaVzQ7yTlWoIRKwPvcFjm40EBehDZkByP/2otNCbwx6GIsCCSXOd6ExFDI5tn9QaRKw2CnfvWY=;7:Fti7UNIdAypxZZ4+K5o9IITRpqmqzwdpz5wT6/wogBUfhbKe1gVenWc8xrU6N+3BJbE/Ze25y2ao+8fuB6lP9LJAZKdspecT1bbI/ruylZx8Cm1fLr5TWuYcoWN4t971caZCEVTNWmbhuLwiyVWIqw== SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: microsemi.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Dec 2018 22:28:12.2679 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 515a730e-ce8f-4801-1bb1-08d65c934601 X-MS-Exchange-CrossTenant-Id: f267a5c8-86d8-4cc9-af71-1fd2c67c8fad X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f267a5c8-86d8-4cc9-af71-1fd2c67c8fad;Ip=[208.19.99.221];Helo=[AUSMBX1.microsemi.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR19MB0935 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: Kevin Barnett Add support for new IUs and parsing of the Firmware Features section of the PQI Config Table to implement the "handshake" between the driver and firmware to communicate firmware features supported and enabled by the driver. Reviewed-by: Ajish Koshy Reviewed-by: Mahesh Rajashekhara Reviewed-by: Murthy Bhat Reviewed-by: Justin Lindley Reviewed-by: Scott Teel Signed-off-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/smartpqi/smartpqi.h | 43 ++++++ drivers/scsi/smartpqi/smartpqi_init.c | 254 ++++++++++++++++++++++++++++++++- 2 files changed, 293 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index e97bf2670315..bbf056ddd026 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h @@ -389,6 +389,35 @@ struct pqi_task_management_response { u8 response_code; }; +struct pqi_vendor_general_request { + struct pqi_iu_header header; + __le16 request_id; + __le16 function_code; + union { + struct { + __le16 first_section; + __le16 last_section; + u8 reserved[48]; + } config_table_update; + + struct { + __le64 buffer_address; + __le32 buffer_length; + u8 reserved[40]; + } ofa_memory_allocation; + } data; +}; + +struct pqi_vendor_general_response { + struct pqi_iu_header header; + __le16 request_id; + __le16 function_code; + __le16 status; + u8 reserved[2]; +}; + +#define PQI_VENDOR_GENERAL_CONFIG_TABLE_UPDATE 0 + struct pqi_aio_error_info { u8 status; u8 service_response; @@ -419,6 +448,7 @@ struct pqi_raid_error_info { #define PQI_REQUEST_IU_GENERAL_ADMIN 0x60 #define PQI_REQUEST_IU_REPORT_VENDOR_EVENT_CONFIG 0x72 #define PQI_REQUEST_IU_SET_VENDOR_EVENT_CONFIG 0x73 +#define PQI_REQUEST_IU_VENDOR_GENERAL 0x75 #define PQI_REQUEST_IU_ACKNOWLEDGE_VENDOR_EVENT 0xf6 #define PQI_RESPONSE_IU_GENERAL_MANAGEMENT 0x81 @@ -430,6 +460,7 @@ struct pqi_raid_error_info { #define PQI_RESPONSE_IU_AIO_PATH_IO_ERROR 0xf3 #define PQI_RESPONSE_IU_AIO_PATH_DISABLED 0xf4 #define PQI_RESPONSE_IU_VENDOR_EVENT 0xf5 +#define PQI_RESPONSE_IU_VENDOR_GENERAL 0xf7 #define PQI_GENERAL_ADMIN_FUNCTION_REPORT_DEVICE_CAPABILITY 0x0 #define PQI_GENERAL_ADMIN_FUNCTION_CREATE_IQ 0x10 @@ -644,6 +675,7 @@ struct pqi_encryption_info { #define PQI_CONFIG_TABLE_MAX_LENGTH ((u16)~0) /* configuration table section IDs */ +#define PQI_CONFIG_TABLE_ALL_SECTIONS (-1) #define PQI_CONFIG_TABLE_SECTION_GENERAL_INFO 0 #define PQI_CONFIG_TABLE_SECTION_FIRMWARE_FEATURES 1 #define PQI_CONFIG_TABLE_SECTION_FIRMWARE_ERRATA 2 @@ -680,6 +712,17 @@ struct pqi_config_table_general_info { /* command */ }; +struct pqi_config_table_firmware_features { + struct pqi_config_table_section_header header; + __le16 num_elements; + u8 features_supported[]; +/* u8 features_requested_by_host[]; */ +/* u8 features_enabled[]; */ +}; + +#define PQI_FIRMWARE_FEATURE_OFA 0 +#define PQI_FIRMWARE_FEATURE_SMP 1 + struct pqi_config_table_debug { struct pqi_config_table_section_header header; __le32 scratchpad; diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index a25a07a0b7f0..72e635cc594c 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -2706,6 +2706,12 @@ static unsigned int pqi_process_io_intr(struct pqi_ctrl_info *ctrl_info, case PQI_RESPONSE_IU_AIO_PATH_IO_SUCCESS: case PQI_RESPONSE_IU_GENERAL_MANAGEMENT: break; + case PQI_RESPONSE_IU_VENDOR_GENERAL: + io_request->status = + get_unaligned_le16( + &((struct pqi_vendor_general_response *) + response)->status); + break; case PQI_RESPONSE_IU_TASK_MANAGEMENT: io_request->status = pqi_interpret_task_management_response( @@ -5947,6 +5953,233 @@ static int pqi_get_ctrl_firmware_version(struct pqi_ctrl_info *ctrl_info) return rc; } +struct pqi_config_table_section_info { + struct pqi_ctrl_info *ctrl_info; + void *section; + u32 section_offset; + void __iomem *section_iomem_addr; +}; + +static inline bool pqi_is_firmware_feature_supported( + struct pqi_config_table_firmware_features *firmware_features, + unsigned int bit_position) +{ + unsigned int byte_index; + + byte_index = bit_position / BITS_PER_BYTE; + + if (byte_index >= le16_to_cpu(firmware_features->num_elements)) + return false; + + return firmware_features->features_supported[byte_index] & + (1 << (bit_position % BITS_PER_BYTE)) ? true : false; +} + +static inline bool pqi_is_firmware_feature_enabled( + struct pqi_config_table_firmware_features *firmware_features, + void __iomem *firmware_features_iomem_addr, + unsigned int bit_position) +{ + unsigned int byte_index; + u8 __iomem *features_enabled_iomem_addr; + + byte_index = (bit_position / BITS_PER_BYTE) + + (le16_to_cpu(firmware_features->num_elements) * 2); + + features_enabled_iomem_addr = firmware_features_iomem_addr + + offsetof(struct pqi_config_table_firmware_features, + features_supported) + byte_index; + + return *((__force u8 *)features_enabled_iomem_addr) & + (1 << (bit_position % BITS_PER_BYTE)) ? true : false; +} + +static inline void pqi_request_firmware_feature( + struct pqi_config_table_firmware_features *firmware_features, + unsigned int bit_position) +{ + unsigned int byte_index; + + byte_index = (bit_position / BITS_PER_BYTE) + + le16_to_cpu(firmware_features->num_elements); + + firmware_features->features_supported[byte_index] |= + (1 << (bit_position % BITS_PER_BYTE)); +} + +static int pqi_config_table_update(struct pqi_ctrl_info *ctrl_info, + u16 first_section, u16 last_section) +{ + struct pqi_vendor_general_request request; + + memset(&request, 0, sizeof(request)); + + request.header.iu_type = PQI_REQUEST_IU_VENDOR_GENERAL; + put_unaligned_le16(sizeof(request) - PQI_REQUEST_HEADER_LENGTH, + &request.header.iu_length); + put_unaligned_le16(PQI_VENDOR_GENERAL_CONFIG_TABLE_UPDATE, + &request.function_code); + put_unaligned_le16(first_section, + &request.data.config_table_update.first_section); + put_unaligned_le16(last_section, + &request.data.config_table_update.last_section); + + return pqi_submit_raid_request_synchronous(ctrl_info, &request.header, + 0, NULL, NO_TIMEOUT); +} + +static int pqi_enable_firmware_features(struct pqi_ctrl_info *ctrl_info, + struct pqi_config_table_firmware_features *firmware_features, + void __iomem *firmware_features_iomem_addr) +{ + void *features_requested; + void __iomem *features_requested_iomem_addr; + + features_requested = firmware_features->features_supported + + le16_to_cpu(firmware_features->num_elements); + + features_requested_iomem_addr = firmware_features_iomem_addr + + (features_requested - (void *)firmware_features); + + memcpy_toio(features_requested_iomem_addr, features_requested, + le16_to_cpu(firmware_features->num_elements)); + + return pqi_config_table_update(ctrl_info, + PQI_CONFIG_TABLE_SECTION_FIRMWARE_FEATURES, + PQI_CONFIG_TABLE_SECTION_FIRMWARE_FEATURES); +} + +struct pqi_firmware_feature { + char *feature_name; + unsigned int feature_bit; + bool supported; + bool enabled; + void (*feature_status)(struct pqi_ctrl_info *ctrl_info, + struct pqi_firmware_feature *firmware_feature); +}; + +static void pqi_firmware_feature_status(struct pqi_ctrl_info *ctrl_info, + struct pqi_firmware_feature *firmware_feature) +{ + if (!firmware_feature->supported) { + dev_info(&ctrl_info->pci_dev->dev, "%s not supported by controller\n", + firmware_feature->feature_name); + return; + } + + if (firmware_feature->enabled) { + dev_info(&ctrl_info->pci_dev->dev, + "%s enabled\n", firmware_feature->feature_name); + return; + } + + dev_err(&ctrl_info->pci_dev->dev, "failed to enable %s\n", + firmware_feature->feature_name); +} + +static inline void pqi_firmware_feature_update(struct pqi_ctrl_info *ctrl_info, + struct pqi_firmware_feature *firmware_feature) +{ + if (firmware_feature->feature_status) + firmware_feature->feature_status(ctrl_info, firmware_feature); +} + +static DEFINE_MUTEX(pqi_firmware_features_mutex); + +static struct pqi_firmware_feature pqi_firmware_features[] = { + { + .feature_name = "Online Firmware Activation", + .feature_bit = PQI_FIRMWARE_FEATURE_OFA, + .feature_status = pqi_firmware_feature_status, + }, + { + .feature_name = "Serial Management Protocol", + .feature_bit = PQI_FIRMWARE_FEATURE_SMP, + .feature_status = pqi_firmware_feature_status, + }, +}; + +static void pqi_process_firmware_features( + struct pqi_config_table_section_info *section_info) +{ + int rc; + struct pqi_ctrl_info *ctrl_info; + struct pqi_config_table_firmware_features *firmware_features; + void __iomem *firmware_features_iomem_addr; + unsigned int i; + unsigned int num_features_supported; + + ctrl_info = section_info->ctrl_info; + firmware_features = section_info->section; + firmware_features_iomem_addr = section_info->section_iomem_addr; + + for (i = 0, num_features_supported = 0; + i < ARRAY_SIZE(pqi_firmware_features); i++) { + if (pqi_is_firmware_feature_supported(firmware_features, + pqi_firmware_features[i].feature_bit)) { + pqi_firmware_features[i].supported = true; + num_features_supported++; + } else { + pqi_firmware_feature_update(ctrl_info, + &pqi_firmware_features[i]); + } + } + + if (num_features_supported == 0) + return; + + for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) { + if (!pqi_firmware_features[i].supported) + continue; + pqi_request_firmware_feature(firmware_features, + pqi_firmware_features[i].feature_bit); + } + + rc = pqi_enable_firmware_features(ctrl_info, firmware_features, + firmware_features_iomem_addr); + if (rc) { + dev_err(&ctrl_info->pci_dev->dev, + "failed to enable firmware features in PQI configuration table\n"); + for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) { + if (!pqi_firmware_features[i].supported) + continue; + pqi_firmware_feature_update(ctrl_info, + &pqi_firmware_features[i]); + } + return; + } + + for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) { + if (!pqi_firmware_features[i].supported) + continue; + if (pqi_is_firmware_feature_enabled(firmware_features, + firmware_features_iomem_addr, + pqi_firmware_features[i].feature_bit)) + pqi_firmware_features[i].enabled = true; + pqi_firmware_feature_update(ctrl_info, + &pqi_firmware_features[i]); + } +} + +static void pqi_init_firmware_features(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) { + pqi_firmware_features[i].supported = false; + pqi_firmware_features[i].enabled = false; + } +} + +static void pqi_process_firmware_features_section( + struct pqi_config_table_section_info *section_info) +{ + mutex_lock(&pqi_firmware_features_mutex); + pqi_init_firmware_features(); + pqi_process_firmware_features(section_info); + mutex_unlock(&pqi_firmware_features_mutex); +} + static int pqi_process_config_table(struct pqi_ctrl_info *ctrl_info) { u32 table_length; @@ -5954,8 +6187,11 @@ static int pqi_process_config_table(struct pqi_ctrl_info *ctrl_info) void __iomem *table_iomem_addr; struct pqi_config_table *config_table; struct pqi_config_table_section_header *section; + struct pqi_config_table_section_info section_info; table_length = ctrl_info->config_table_length; + if (table_length == 0) + return 0; config_table = kmalloc(table_length, GFP_KERNEL); if (!config_table) { @@ -5972,13 +6208,22 @@ static int pqi_process_config_table(struct pqi_ctrl_info *ctrl_info) ctrl_info->config_table_offset; memcpy_fromio(config_table, table_iomem_addr, table_length); + section_info.ctrl_info = ctrl_info; section_offset = get_unaligned_le32(&config_table->first_section_offset); while (section_offset) { section = (void *)config_table + section_offset; + section_info.section = section; + section_info.section_offset = section_offset; + section_info.section_iomem_addr = + table_iomem_addr + section_offset; + switch (get_unaligned_le16(§ion->section_id)) { + case PQI_CONFIG_TABLE_SECTION_FIRMWARE_FEATURES: + pqi_process_firmware_features_section(§ion_info); + break; case PQI_CONFIG_TABLE_SECTION_HEARTBEAT: if (pqi_disable_heartbeat) dev_warn(&ctrl_info->pci_dev->dev, @@ -6123,10 +6368,6 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) ctrl_info->pqi_mode_enabled = true; pqi_save_ctrl_mode(ctrl_info, PQI_MODE); - rc = pqi_process_config_table(ctrl_info); - if (rc) - return rc; - rc = pqi_alloc_admin_queues(ctrl_info); if (rc) { dev_err(&ctrl_info->pci_dev->dev, @@ -6188,6 +6429,11 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) pqi_change_irq_mode(ctrl_info, IRQ_MODE_MSIX); ctrl_info->controller_online = true; + + rc = pqi_process_config_table(ctrl_info); + if (rc) + return rc; + pqi_start_heartbeat_timer(ctrl_info); rc = pqi_enable_events(ctrl_info);