From patchwork Fri Dec 7 22:30:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Don Brace X-Patchwork-Id: 10718985 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 1392B109C for ; Fri, 7 Dec 2018 22:30:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 01F382ABF4 for ; Fri, 7 Dec 2018 22:30:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E9C4E2F2E1; Fri, 7 Dec 2018 22:30:21 +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 9E7CD2ABF4 for ; Fri, 7 Dec 2018 22:30:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726081AbeLGWaU (ORCPT ); Fri, 7 Dec 2018 17:30:20 -0500 Received: from mail-eopbgr680054.outbound.protection.outlook.com ([40.107.68.54]:62380 "EHLO NAM04-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726070AbeLGWaT (ORCPT ); Fri, 7 Dec 2018 17:30:19 -0500 Received: from MWHPR19CA0056.namprd19.prod.outlook.com (2603:10b6:300:94::18) by MWHPR19MB0942.namprd19.prod.outlook.com (2603:10b6:300:a4::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1404.22; Fri, 7 Dec 2018 22:30:08 +0000 Received: from BN1BFFO11FD025.protection.gbl (2a01:111:f400:7c10::1:116) by MWHPR19CA0056.outlook.office365.com (2603:10b6:300:94::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1404.17 via Frontend Transport; Fri, 7 Dec 2018 22:30:08 +0000 Received-SPF: Pass (protection.outlook.com: domain of microsemi.com designates 208.19.100.23 as permitted sender) receiver=protection.outlook.com; client-ip=208.19.100.23; helo=AVMBX3.microsemi.net; Received: from AVMBX3.microsemi.net (208.19.100.23) by BN1BFFO11FD025.mail.protection.outlook.com (10.58.144.88) 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:30:07 +0000 Received: from AVMBX2.microsemi.net (10.100.34.32) by AVMBX3.microsemi.net (10.100.34.33) 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 14:30:06 -0800 Received: from [127.0.1.1] (10.238.32.34) by avmbx2.microsemi.net (10.100.34.32) with Microsoft SMTP Server id 15.1.1531.3 via Frontend Transport; Fri, 7 Dec 2018 14:30:05 -0800 Subject: [PATCH 19/20] smartpqi: add smp_utils support From: Don Brace To: , , , , , , , , , , , CC: Date: Fri, 7 Dec 2018 16:30:05 -0600 Message-ID: <154422180514.1218.12509690407248653605.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.100.23;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(7916004)(396003)(39860400002)(346002)(136003)(376002)(2980300002)(189003)(199004)(23676004)(103116003)(47776003)(230700001)(81166006)(58126008)(81156014)(8936002)(316002)(110136005)(8676002)(5660300001)(97736004)(2486003)(16576012)(305945005)(50466002)(33716001)(106002)(106466001)(69596002)(68736007)(2906002)(9686003)(53936002)(336012)(4326008)(2201001)(26005)(77096007)(4744004)(356004)(126002)(446003)(11346002)(14444005)(575784001)(476003)(486006)(6346003)(76176011)(478600001)(86362001)(33896004)(44832011)(186003)(921003)(83996005)(2101003)(1121003);DIR:OUT;SFP:1101;SCL:1;SRVR:MWHPR19MB0942;H:AVMBX3.microsemi.net;FPR:;SPF:Pass;LANG:en;PTR:InfoDomainNonexistent;MX:1;A:1; X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11FD025;1:s67w05o+7BXb59e6rLmr8C8mXtZu4y3T9AYGiRthDRggzKhi+7xy8bryJz367Q5DuGnzrA8AT73PtWYf9e5JqmFkgP5c8fivFl1q0EaHZ8n8LaTLBxEEnDFx1b3OkTjh X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 6206a1dd-8ac7-4421-3cf6-08d65c938ad9 X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:(2390098)(7020095)(4652040)(8989299)(5600074)(711020)(4608076)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(2017052603328)(7153060);SRVR:MWHPR19MB0942; X-Microsoft-Exchange-Diagnostics: 1;MWHPR19MB0942;3:1+vvJM3MrupzsewL0EcT+cwPEYbCRIPHhB9TPJALow8c7SMLpND+/yYYIhfOkG/zxwY2yHsPsv0MPYY9XXGMc9dmkjGyMYylSMnmZXuNGYGeakpT5fbq8TLOlfqQFHqqQQByO+uRsrzEeq4C/v3Yrub8La3KmtudHI7ZJONLDLHRqOX7Yj0BSs21EVgtQhfGzLgjQzn/rUg/e2Eg0HlLBW64hfr3+E2/K4BMjTWtdXPM9ANs9Wlxsh24KtOZws+kfenlJQJWbYZo3/r8A8Xwh0k1YuysAuk63+Yxvgmvy/6r8MRWyfdnuBZRRSfWRPYCoflxiHEmIQlyP/j6ooYblV9cH15ewb6tLRL2uunWMEg=;25:5PauVU2qLong4T0Cm16nHzn4UiYUQzxdCeS+Li+3iHpDsbwa25re6ea5LxU4+ED040YE3fCkAPkp8pOcFZ2K8mpm1HKa1/cpE+lW3t6LLvwcmTagC/zi/1G57LdK/NHlPpv0NVip5waleEPslc8Pw3J8bulIL0dy/3alT55xESIu2iUFqG1MQCKD2EkWXYhyEskMGV7pkOTW7ihk6wo16JfLRB9cyJZLXaSPfoNWn6mNKN7vJPqVSNL4B9RGkhXBlP2Euzy6ij8fbLD5HB2T10JNPaM1cnftbYadoWZOUfzW/hFynKF5PbL3YWXvuKIPYSBhyR+zigYLEsrQk2yRWA== X-MS-TrafficTypeDiagnostic: MWHPR19MB0942: X-Microsoft-Exchange-Diagnostics: 1;MWHPR19MB0942;31:EUyfHvLaMhLz7RdxN9Wl5leckiU0dwSb4HmSUm9STsUvFYXAVCQvS0ClVpMFz13RNg69nTeukj0YojypC6gK9Jg16DYreONA/poaEotzllJlN1ry1mxoTyn0HZB9Pj1wVWblIyflKi+SKY6WFRmKu1wGK9zo2GQBXYk1tPYBLKLrMxys7O0VhTFh7dC7mFE3NDYfcLZpn/Vo5XKCZ9BFbrzcenTvjEZZD3gtwY4aj9I=;20:IyEw1ne2oI7jAVYhBn+KjoUVIE7DZzZnBXLkmk8KVh1SSZHS2pFdP504NBn/dEMwkdMEn3KWWFaNKiDOe1m5dF91qEWFXNudgV/K+Ji4rwc4Ad8EyEd0yvhtg9C7Qv6RR2SEtL73X4IBFLXcaAKZXuqr/uQax9M6Fh2ojVQzuWRI3JLQYdI1x8+9N7h3UVUaqgtNDw9Zx43XszjMo+n88+GvwuaYEGEg6WrK3l86UnXn2uRmfcuIgt10WoR+oNjD5+3/QCdSxWAV64whRUiDz2/NyuRwY4seelVF/4aV3O8GabNmIttOhtTfeYqdE0E0yELpd7zeL1/5FqyWYUG7M8R9DneIZjWuOH2jQWXQc/d/nde50yoC7WDIiIBbcscMyW1qc9ctZ76wHj0nE3OPJkITSoZkvtAKrKO6rtN8rNGvnqOVFzEILKkaaCy3Z/MBc8OnjZUrCP5lg5MsnK6sCkDH7OqiSc8dLqmZvsiSPxeinPsI2HQqz1FD4yP5U6ZZeavalIRWm2oPBFJwo9jCEgdsl94TSCy7kNznvFza/vSFsBRXUXtaNRDuhRKU47yWhzuPQKq7WHEi9OA5VEC8OgE5h3guLWConJOjnAYrWXM= 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:MWHPR19MB0942;BCL:0;PCL:0;RULEID:;SRVR:MWHPR19MB0942; X-Microsoft-Exchange-Diagnostics: 1;MWHPR19MB0942;4:FrJfGzzOFKfE87GQxKZzyX27Vy80XI58E4NWHWIoxsVzDDfzZL34XetS4kNKcjOokOEjO330i5ClZlCPV7oj7qRLY2EaFvJxB1pV/u2lCAXMcw2zJXga897uxhHNpc77pOBpkFiBH1kJtAFQIbhpmPY0jmhIMDsEg8nwB9jYzxnESzSq5usSBGqjhM6jAMefRaGExUh+Pmo9uuMiyMh9rX7Tb7ES9etNWfjY/PG6Wuh8CRtXqtAtJ1AzhE2ygAPxa/1j3dW8aKIqDZEJJkherg== X-Forefront-PRVS: 0879599414 X-Microsoft-Exchange-Diagnostics: =?utf-8?q?1=3BMWHPR19MB0942=3B23=3ArTeUlhv?= =?utf-8?q?HrMDxVyEeI7Z/GHISvVRbl+j59I3r6XCDiLGM5M5mSONM8lBCDyIbgmiRw5lrVV2C?= =?utf-8?q?ZpGDmafLJWzAwmwgCA7fVYu9q9Yq86jN6kJ0LFXp3LijxfVxPzXNY1Z+4UKBrZ7iN?= =?utf-8?q?ZbP3bC1Ildx/R5jPE2jWyQCtgXefH82bt/NqTs8gICTCi5PGMbjSkiSqIfbwQUlX8?= =?utf-8?q?Jx4oNjmBJnspiv+pV2EMQh+gpdlHxWNRj+g3oOgWhLaxdTY48LgB1BKWuz+NgJL7d?= =?utf-8?q?hIUgAFvYwziwaKuIB9+Bff1vi0wvSsxlauqc6bi89ilnxwGehKR7kzsBn9DifZXYM?= =?utf-8?q?zLqoe20Jtv112BDMD4N7WpzG2804rRdI9Fwd6hO/2BwXDywiEJEMnB8XS0FvX1uvt?= =?utf-8?q?ddGu4J9MfGz4jlmjxThJvEkcSQLHb6BzOXCT6lg7Bj0FrgJaCpBJalXb+b4115890?= =?utf-8?q?G2WhpsT+grTyq3bAwolzqFcdk4Io9O9aF86PTc/21/sDZuMvmjF9rqi8E7LfGHAfO?= =?utf-8?q?jh64zXtTuydixaDDwHPvrtJ+82dl6Ivpr8TNQsXJUl/IOKapsE4aNXEsJDMy59WWd?= =?utf-8?q?NBAnsmq4pp8XvZiTLz8uzPi5ZDBChzlyFm7pMvW976rZepFKH8ALSqpoUdzWjqBlk?= =?utf-8?q?VHyhlrRDbOxR4dlFNDguYj/Ha4gxyzS9BiASmqKDsdsTrpC/AInSY6RaSLlDKw4rQ?= =?utf-8?q?G4bjW7N/00yULB9OpAdY2awcpabUPdQuyWiNZeMwW9xvkIqoxqqW2ogJSS+3GCGYn?= =?utf-8?q?wlOfYpnudg2huIbI1QNxHpT5nM/QOWJnQdI0lYhlb+uCiFMF9fogc7YuX4tMCs7e5?= =?utf-8?q?FB3PAgzCf54q6r1rAAlyzGRU0EASfS9pOXcCFORqlNESjvB29ViDb7jMvKzdCKW73?= =?utf-8?q?Lu0jYMh/jCodcUgEdwfSakvpKujUcCDWIqiskwPhU7vBIyrcjr3TRktuIYdn5c/1+?= =?utf-8?q?hWJojga8PX5Na5EOhgOG/yO4MSl4eknRi2IyOuOcY5qhNL6uXZoIU3UEtI6AERK9M?= =?utf-8?q?p4ax2mPei7XuXjT0aV7f1t40aupvn1TMxAr8cU11oKuP2bzlKObmlTF9jDT6kaGra?= =?utf-8?q?h2J6r0j91lt927z/RBauwHrIy0X98uW4KjkCh5zmNYe0Sgsk1KnmyKPl8dtmbnDtK?= =?utf-8?q?1kqjnLdxFZJplibFs66H6Pr+pCbdX8VRVDadZ1Rfc7sE1uSFfptHOGn/Lfh0G0kmX?= =?utf-8?q?zAU+jWHeg6tLTc20BiXXBPTkEl7D8EECW2JQOl4fbMv+50NbWdSP4rQ8W9uw=3D?= =?utf-8?q?=3D?= X-Microsoft-Antispam-Message-Info: CX9bchX7p2inkdHyXJofk1Xyetyyl1bAfC/WvnfAk16DXlGoIEt1SvPQx82AtY+vMAmgkmtjRQY/n0x1ctYid7mbieDs5IYtny/gn2Sl5Nt26f7H+nB4so3V04LMr0mtrAvdhiO3d6fBw6QAGG2G4P0NqNfi0wdr8jeZKGGPizmD2dQvYuiBDFmNvE6LUm7HXCGm4IKgw+fM4sI5Sqn2X5rqI6TAW+mNqQ1Smx2UiWpi9C4qjQsmD8yCVOeT5yjSeeugB9w+2wUH8RUHfTlYKpmHaDnkwFjh40Jvloamd1RyXCWmqc/2TO5632WlTpQzCaII/DA+UDQzDjIrjA7YFz+cniOvaIodc+fX0g68w3w= X-Microsoft-Exchange-Diagnostics: 1;MWHPR19MB0942;6:VQeIJ4lc7SNll8rkj2jQbY8B/sgQys4Lrtn7LzeuGPBo9fYKE/SA2v4HUhibPwhKskM3YMgRXtAA2K95EcoVShiTSMfI1A6p692hM++THV31ki24Ph1sjQCptxnposxoLBEkFjFEGbcRhrZQl4rt+iKrA3/ob9aPmYkYatb57x0ppd/nNVQ5Z+01VaEb1u/9vzCaW6U2Ck/OuocmQVtzDovzg8IoS2fJ1LnV1e2as8DfOI+uK19XU1NkCwqXl4ISPDzY2H+112Eoc5Yre76C4B2c+PN5mEarYQaOVBhQ4Vzehj0wEMl4MiICXaQMp3tpPx5QSlQuobzbJ/NTtB64aE+7HQILnS7TQ/dc8N3QvIdwF3aDlZtB0JCjPuYmxBRma5rG9OXzbDrfY/GMJGBWH0C2XRt8pfOk08byu3mKg/+NoBNw9M05OGyfHf6tp/9jr7Uu72kKzlFMUhhrGTSt+A==;5:1yGHrf0lgoDJlLkmCvxi1yqe6KqFvqDuLzKoBBIEpCStZLdG4+NoyW+Zr+bf1Ztfo5lDNKAaUj72546EBCvR/ErUMJWHB0rdLDU1Es0+O6h6kWkLpiuuPKvHMMDV3pRlb779X9x50HV2t6sxU3SqJnziuHLbs3K+ue6rZQC93A8=;7:EPP1kZrkGRc9EwPCVatAfkRmvOiAcAHsy/Yd+2nsHpHvatp9f1PWu2GJMclwJR4j1HCJadAWKfCF6pZsFxtJ7NrnzEHoRe6+qEGA1BBLbZ1hw5ihXSh7IgxLv9lFaBHnPjpOI4JgyVVCfq8djVlOdw== SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: microsemi.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Dec 2018 22:30:07.7538 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 6206a1dd-8ac7-4421-3cf6-08d65c938ad9 X-MS-Exchange-CrossTenant-Id: f267a5c8-86d8-4cc9-af71-1fd2c67c8fad X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f267a5c8-86d8-4cc9-af71-1fd2c67c8fad;Ip=[208.19.100.23];Helo=[AVMBX3.microsemi.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR19MB0942 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 Reviewed-by: Scott Benesh Reviewed-by: Mahesh Rajashekhara Reviewed-by: Scott Teel Reviewed-by: Dave Carroll Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/smartpqi/smartpqi.h | 89 +++++++++++++ drivers/scsi/smartpqi/smartpqi_init.c | 131 ++++++++++++------- drivers/scsi/smartpqi/smartpqi_sas_transport.c | 164 +++++++++++++++++++++++- 3 files changed, 324 insertions(+), 60 deletions(-) diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index 4f52b5be3693..ba499a636f43 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h @@ -21,6 +21,9 @@ #if !defined(_SMARTPQI_H) #define _SMARTPQI_H +#include +#include + #pragma pack(1) #define PQI_DEVICE_SIGNATURE "PQI DREG" @@ -855,6 +858,7 @@ struct pqi_scsi_dev { u8 unique_id[16]; u8 is_physical_device : 1; u8 is_external_raid_device : 1; + u8 is_expander_smp_device : 1; u8 target_lun_valid : 1; u8 device_gone : 1; u8 new_device : 1; @@ -964,6 +968,7 @@ struct pqi_sas_node { struct pqi_sas_port { struct list_head port_list_entry; u64 sas_address; + struct pqi_scsi_dev *device; struct sas_port *port; int next_phy_index; struct list_head phy_list_head; @@ -1129,11 +1134,14 @@ enum pqi_ctrl_mode { #define BMIC_WRITE 0x27 #define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64 #define BMIC_SENSE_SUBSYSTEM_INFORMATION 0x66 +#define BMIC_CSMI_PASSTHRU 0x68 #define BMIC_WRITE_HOST_WELLNESS 0xa5 #define BMIC_FLUSH_CACHE 0xc2 #define BMIC_SET_DIAG_OPTIONS 0xf4 #define BMIC_SENSE_DIAG_OPTIONS 0xf5 +#define CSMI_CC_SAS_SMP_PASSTHRU 0X17 + #define SA_FLUSH_CACHE 0x1 #define MASKED_DEVICE(lunid) ((lunid)[3] & 0xc0) @@ -1160,6 +1168,10 @@ struct bmic_identify_controller { u8 reserved3[32]; }; +#define SA_EXPANDER_SMP_DEVICE 0x05 +/*SCSI Invalid Device Type for SAS devices*/ +#define PQI_SAS_SCSI_INVALID_DEVTYPE 0xff + struct bmic_identify_physical_device { u8 scsi_bus; /* SCSI Bus number on controller */ u8 scsi_id; /* SCSI ID on this bus */ @@ -1240,6 +1252,50 @@ struct bmic_identify_physical_device { u8 padding_to_multiple_of_512[9]; }; +struct bmic_smp_request { + u8 frame_type; + u8 function; + u8 allocated_response_length; + u8 request_length; + u8 additional_request_bytes[1016]; +}; + +struct bmic_smp_response { + u8 frame_type; + u8 function; + u8 function_result; + u8 response_length; + u8 additional_response_bytes[1016]; +}; + +struct bmic_csmi_ioctl_header { + __le32 header_length; + u8 signature[8]; + __le32 timeout; + __le32 control_code; + __le32 return_code; + __le32 length; +}; + +struct bmic_csmi_smp_passthru { + u8 phy_identifier; + u8 port_identifier; + u8 connection_rate; + u8 reserved; + __be64 destination_sas_address; + __le32 request_length; + struct bmic_smp_request request; + u8 connection_status; + u8 reserved1[3]; + __le32 response_length; + struct bmic_smp_response response; +}; + +struct bmic_csmi_smp_passthru_buffer { + struct bmic_csmi_ioctl_header ioctl_header; + struct bmic_csmi_smp_passthru parameters; +}; + struct bmic_flush_cache { u8 disable_flag; u8 system_power_action; @@ -1263,6 +1319,36 @@ struct bmic_diag_options { #pragma pack() +static inline struct pqi_ctrl_info *shost_to_hba(struct Scsi_Host *shost) +{ + void *hostdata = shost_priv(shost); + + return *((struct pqi_ctrl_info **)hostdata); +} + +static inline bool pqi_ctrl_offline(struct pqi_ctrl_info *ctrl_info) +{ + return !ctrl_info->controller_online; +} + +static inline void pqi_ctrl_busy(struct pqi_ctrl_info *ctrl_info) +{ + atomic_inc(&ctrl_info->num_busy_threads); +} + +static inline void pqi_ctrl_unbusy(struct pqi_ctrl_info *ctrl_info) +{ + atomic_dec(&ctrl_info->num_busy_threads); +} + +static inline bool pqi_ctrl_blocked(struct pqi_ctrl_info *ctrl_info) +{ + return ctrl_info->block_requests; +} + +void pqi_sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost, + struct sas_rphy *rphy); + int pqi_add_sas_host(struct Scsi_Host *shost, struct pqi_ctrl_info *ctrl_info); void pqi_delete_sas_host(struct pqi_ctrl_info *ctrl_info); int pqi_add_sas_device(struct pqi_sas_node *pqi_sas_node, @@ -1271,6 +1357,9 @@ void pqi_remove_sas_device(struct pqi_scsi_dev *device); struct pqi_scsi_dev *pqi_find_device_by_sas_rphy( struct pqi_ctrl_info *ctrl_info, struct sas_rphy *rphy); void pqi_prep_for_scsi_done(struct scsi_cmnd *scmd); +int pqi_csmi_smp_passthru(struct pqi_ctrl_info *ctrl_info, + struct bmic_csmi_smp_passthru_buffer *buffer, size_t buffer_length, + struct pqi_raid_error_info *error_info); extern struct sas_function_template pqi_sas_transport_functions; diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index f9812281988c..8d94028d0a9d 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -193,13 +193,6 @@ static inline bool pqi_scsi3addr_equal(u8 *scsi3addr1, u8 *scsi3addr2) return memcmp(scsi3addr1, scsi3addr2, 8) == 0; } -static inline struct pqi_ctrl_info *shost_to_hba(struct Scsi_Host *shost) -{ - void *hostdata = shost_priv(shost); - - return *((struct pqi_ctrl_info **)hostdata); -} - static inline bool pqi_is_logical_device(struct pqi_scsi_dev *device) { return !device->is_physical_device; @@ -210,11 +203,6 @@ static inline bool pqi_is_external_raid_addr(u8 *scsi3addr) return scsi3addr[2] != 0; } -static inline bool pqi_ctrl_offline(struct pqi_ctrl_info *ctrl_info) -{ - return !ctrl_info->controller_online; -} - static inline void pqi_check_ctrl_health(struct pqi_ctrl_info *ctrl_info) { if (ctrl_info->controller_online) @@ -253,11 +241,6 @@ static inline void pqi_ctrl_unblock_requests(struct pqi_ctrl_info *ctrl_info) scsi_unblock_requests(ctrl_info->scsi_host); } -static inline bool pqi_ctrl_blocked(struct pqi_ctrl_info *ctrl_info) -{ - return ctrl_info->block_requests; -} - static unsigned long pqi_wait_if_ctrl_blocked(struct pqi_ctrl_info *ctrl_info, unsigned long timeout_msecs) { @@ -287,16 +270,6 @@ static unsigned long pqi_wait_if_ctrl_blocked(struct pqi_ctrl_info *ctrl_info, return remaining_msecs; } -static inline void pqi_ctrl_busy(struct pqi_ctrl_info *ctrl_info) -{ - atomic_inc(&ctrl_info->num_busy_threads); -} - -static inline void pqi_ctrl_unbusy(struct pqi_ctrl_info *ctrl_info) -{ - atomic_dec(&ctrl_info->num_busy_threads); -} - static inline void pqi_ctrl_wait_until_quiesced(struct pqi_ctrl_info *ctrl_info) { while (atomic_read(&ctrl_info->num_busy_threads) > @@ -477,6 +450,13 @@ static int pqi_build_raid_path_request(struct pqi_ctrl_info *ctrl_info, cdb[6] = cmd; put_unaligned_be16(cdb_length, &cdb[7]); break; + case BMIC_CSMI_PASSTHRU: + request->data_direction = SOP_BIDIRECTIONAL; + cdb[0] = BMIC_WRITE; + cdb[5] = CSMI_CC_SAS_SMP_PASSTHRU; + cdb[6] = cmd; + put_unaligned_be16(cdb_length, &cdb[7]); + break; default: dev_err(&ctrl_info->pci_dev->dev, "unknown command 0x%c\n", cmd); @@ -718,6 +698,13 @@ static int pqi_flush_cache(struct pqi_ctrl_info *ctrl_info, return rc; } +int pqi_csmi_smp_passthru(struct pqi_ctrl_info *ctrl_info, + struct bmic_csmi_smp_passthru_buffer *buffer, size_t buffer_length, + struct pqi_raid_error_info *error_info) +{ + return pqi_send_ctrl_raid_with_error(ctrl_info, BMIC_CSMI_PASSTHRU, + buffer, buffer_length, error_info); +} #define PQI_FETCH_PTRAID_DATA (1UL<<31) @@ -1303,6 +1290,9 @@ static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info, u8 *buffer; unsigned int retries; + if (device->is_expander_smp_device) + return 0; + buffer = kmalloc(64, GFP_KERNEL); if (!buffer) return -ENOMEM; @@ -1590,6 +1580,14 @@ static enum pqi_find_result pqi_scsi_find_entry(struct pqi_ctrl_info *ctrl_info, return DEVICE_NOT_FOUND; } +static inline const char *pqi_device_type(struct pqi_scsi_dev *device) +{ + if (device->is_expander_smp_device) + return "Enclosure SMP "; + + return scsi_device_type(device->devtype); +} + #define PQI_DEV_INFO_BUFFER_LENGTH 128 static void pqi_dev_info(struct pqi_ctrl_info *ctrl_info, @@ -1625,7 +1623,7 @@ static void pqi_dev_info(struct pqi_ctrl_info *ctrl_info, count += snprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count, " %s %.8s %.16s ", - scsi_device_type(device->devtype), + pqi_device_type(device), device->vendor, device->model); @@ -1670,6 +1668,8 @@ static void pqi_scsi_update_device(struct pqi_scsi_dev *existing_device, existing_device->is_physical_device = new_device->is_physical_device; existing_device->is_external_raid_device = new_device->is_external_raid_device; + existing_device->is_expander_smp_device = + new_device->is_expander_smp_device; existing_device->aio_enabled = new_device->aio_enabled; memcpy(existing_device->vendor, new_device->vendor, sizeof(existing_device->vendor)); @@ -1726,6 +1726,14 @@ static inline void pqi_fixup_botched_add(struct pqi_ctrl_info *ctrl_info, device->keep_device = false; } +static inline bool pqi_is_device_added(struct pqi_scsi_dev *device) +{ + if (device->is_expander_smp_device) + return device->sas_port != NULL; + + return device->sdev != NULL; +} + static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *new_device_list[], unsigned int num_new_devices) { @@ -1820,7 +1828,7 @@ static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info, } else { pqi_dev_info(ctrl_info, "removed", device); } - if (device->sdev) + if (pqi_is_device_added(device)) pqi_remove_device(ctrl_info, device); list_del(&device->delete_list_entry); pqi_free_device(device); @@ -1842,7 +1850,7 @@ static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info, /* Expose any new devices. */ list_for_each_entry_safe(device, next, &add_list, add_list_entry) { - if (!device->sdev) { + if (!pqi_is_device_added(device)) { pqi_dev_info(ctrl_info, "added", device); rc = pqi_add_device(ctrl_info, device); if (rc) { @@ -1859,7 +1867,12 @@ static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info, static bool pqi_is_supported_device(struct pqi_scsi_dev *device) { - bool is_supported = false; + bool is_supported; + + if (device->is_expander_smp_device) + return true; + + is_supported = false; switch (device->devtype) { case TYPE_DISK: @@ -1893,6 +1906,24 @@ static inline bool pqi_skip_device(u8 *scsi3addr) return false; } +static inline bool pqi_is_device_with_sas_address(struct pqi_scsi_dev *device) +{ + if (!device->is_physical_device) + return false; + + if (device->is_expander_smp_device) + return true; + + switch (device->devtype) { + case TYPE_DISK: + case TYPE_ZBC: + case TYPE_ENCLOSURE: + return true; + } + + return false; +} + static inline bool pqi_expose_device(struct pqi_scsi_dev *device) { return !device->is_physical_device || @@ -2007,9 +2038,14 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) memcpy(device->scsi3addr, scsi3addr, sizeof(device->scsi3addr)); device->is_physical_device = is_physical_device; - if (!is_physical_device) + if (is_physical_device) { + if (phys_lun_ext_entry->device_type == + SA_EXPANDER_SMP_DEVICE) + device->is_expander_smp_device = true; + } else { device->is_external_raid_device = pqi_is_external_raid_addr(scsi3addr); + } /* Gather information about the device. */ rc = pqi_get_device_info(ctrl_info, device); @@ -2042,30 +2078,23 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) device->wwid = phys_lun_ext_entry->wwid; if ((phys_lun_ext_entry->device_flags & REPORT_PHYS_LUN_DEV_FLAG_AIO_ENABLED) && - phys_lun_ext_entry->aio_handle) + phys_lun_ext_entry->aio_handle) { device->aio_enabled = true; + device->aio_handle = + phys_lun_ext_entry->aio_handle; + } + if (device->devtype == TYPE_DISK || + device->devtype == TYPE_ZBC) { + pqi_get_physical_disk_info(ctrl_info, + device, id_phys); + } } else { memcpy(device->volume_id, log_lun_ext_entry->volume_id, sizeof(device->volume_id)); } - switch (device->devtype) { - case TYPE_DISK: - case TYPE_ZBC: - case TYPE_ENCLOSURE: - if (device->is_physical_device) { - device->sas_address = - get_unaligned_be64(&device->wwid); - if (device->devtype == TYPE_DISK || - device->devtype == TYPE_ZBC) { - device->aio_handle = - phys_lun_ext_entry->aio_handle; - pqi_get_physical_disk_info(ctrl_info, - device, id_phys); - } - } - break; - } + if (pqi_is_device_with_sas_address(device)) + device->sas_address = get_unaligned_be64(&device->wwid); new_device_list[num_valid_devices++] = device; } @@ -2108,7 +2137,7 @@ static void pqi_remove_all_scsi_devices(struct pqi_ctrl_info *ctrl_info) if (!device) break; - if (device->sdev) + if (pqi_is_device_added(device)) pqi_remove_device(ctrl_info, device); pqi_free_device(device); } diff --git a/drivers/scsi/smartpqi/smartpqi_sas_transport.c b/drivers/scsi/smartpqi/smartpqi_sas_transport.c index b209a35e482e..0e4ef215115f 100644 --- a/drivers/scsi/smartpqi/smartpqi_sas_transport.c +++ b/drivers/scsi/smartpqi/smartpqi_sas_transport.c @@ -17,9 +17,11 @@ */ #include +#include #include #include #include +#include #include "smartpqi.h" static struct pqi_sas_phy *pqi_alloc_sas_phy(struct pqi_sas_port *pqi_sas_port) @@ -97,14 +99,32 @@ static int pqi_sas_port_add_rphy(struct pqi_sas_port *pqi_sas_port, identify = &rphy->identify; identify->sas_address = pqi_sas_port->sas_address; - identify->initiator_port_protocols = SAS_PROTOCOL_STP; - identify->target_port_protocols = SAS_PROTOCOL_STP; + + if (pqi_sas_port->device && + pqi_sas_port->device->is_expander_smp_device) { + identify->initiator_port_protocols = SAS_PROTOCOL_SMP; + identify->target_port_protocols = SAS_PROTOCOL_SMP; + } else { + identify->initiator_port_protocols = SAS_PROTOCOL_STP; + identify->target_port_protocols = SAS_PROTOCOL_STP; + } return sas_rphy_add(rphy); } +static struct sas_rphy *pqi_sas_rphy_alloc(struct pqi_sas_port *pqi_sas_port) +{ + if (pqi_sas_port->device && + pqi_sas_port->device->is_expander_smp_device) + return sas_expander_alloc(pqi_sas_port->port, + SAS_FANOUT_EXPANDER_DEVICE); + + return sas_end_device_alloc(pqi_sas_port->port); +} + static struct pqi_sas_port *pqi_alloc_sas_port( - struct pqi_sas_node *pqi_sas_node, u64 sas_address) + struct pqi_sas_node *pqi_sas_node, u64 sas_address, + struct pqi_scsi_dev *device) { int rc; struct pqi_sas_port *pqi_sas_port; @@ -127,6 +147,7 @@ static struct pqi_sas_port *pqi_alloc_sas_port( pqi_sas_port->port = port; pqi_sas_port->sas_address = sas_address; + pqi_sas_port->device = device; list_add_tail(&pqi_sas_port->port_list_entry, &pqi_sas_node->port_list_head); @@ -146,7 +167,7 @@ static void pqi_free_sas_port(struct pqi_sas_port *pqi_sas_port) struct pqi_sas_phy *next; list_for_each_entry_safe(pqi_sas_phy, next, - &pqi_sas_port->phy_list_head, phy_list_entry) + &pqi_sas_port->phy_list_head, phy_list_entry) pqi_free_sas_phy(pqi_sas_phy); sas_port_delete(pqi_sas_port->port); @@ -176,7 +197,7 @@ static void pqi_free_sas_node(struct pqi_sas_node *pqi_sas_node) return; list_for_each_entry_safe(pqi_sas_port, next, - &pqi_sas_node->port_list_head, port_list_entry) + &pqi_sas_node->port_list_head, port_list_entry) pqi_free_sas_port(pqi_sas_port); kfree(pqi_sas_node); @@ -206,13 +227,14 @@ int pqi_add_sas_host(struct Scsi_Host *shost, struct pqi_ctrl_info *ctrl_info) struct pqi_sas_port *pqi_sas_port; struct pqi_sas_phy *pqi_sas_phy; - parent_dev = &shost->shost_gendev; + parent_dev = &shost->shost_dev; pqi_sas_node = pqi_alloc_sas_node(parent_dev); if (!pqi_sas_node) return -ENOMEM; - pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node, ctrl_info->sas_address); + pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node, + ctrl_info->sas_address, NULL); if (!pqi_sas_port) { rc = -ENODEV; goto free_sas_node; @@ -254,11 +276,12 @@ int pqi_add_sas_device(struct pqi_sas_node *pqi_sas_node, struct pqi_sas_port *pqi_sas_port; struct sas_rphy *rphy; - pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node, device->sas_address); + pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node, + device->sas_address, device); if (!pqi_sas_port) return -ENOMEM; - rphy = sas_end_device_alloc(pqi_sas_port->port); + rphy = pqi_sas_rphy_alloc(pqi_sas_port); if (!rphy) { rc = -ENODEV; goto free_sas_port; @@ -329,6 +352,128 @@ static int pqi_sas_phy_speed(struct sas_phy *phy, return -EINVAL; } +#define CSMI_IOCTL_TIMEOUT 60 +#define SMP_CRC_FIELD_LENGTH 4 + +static struct bmic_csmi_smp_passthru_buffer * +pqi_build_csmi_smp_passthru_buffer(struct sas_rphy *rphy, + struct bsg_job *job) +{ + struct bmic_csmi_smp_passthru_buffer *smp_buf; + struct bmic_csmi_ioctl_header *ioctl_header; + struct bmic_csmi_smp_passthru *parameters; + u32 req_size; + u32 resp_size; + + smp_buf = kzalloc(sizeof(*smp_buf), GFP_KERNEL); + if (!smp_buf) + return NULL; + + req_size = job->request_payload.payload_len; + resp_size = job->reply_payload.payload_len; + + ioctl_header = &smp_buf->ioctl_header; + put_unaligned_le32(sizeof(smp_buf->ioctl_header), + &ioctl_header->header_length); + put_unaligned_le32(CSMI_IOCTL_TIMEOUT, &ioctl_header->timeout); + put_unaligned_le32(CSMI_CC_SAS_SMP_PASSTHRU, + &ioctl_header->control_code); + put_unaligned_le32(sizeof(smp_buf->parameters), &ioctl_header->length); + + parameters = &smp_buf->parameters; + parameters->phy_identifier = rphy->identify.phy_identifier; + parameters->port_identifier = 0; + parameters->connection_rate = 0; + put_unaligned_be64(rphy->identify.sas_address, + ¶meters->destination_sas_address); + + if (req_size > SMP_CRC_FIELD_LENGTH) + req_size -= SMP_CRC_FIELD_LENGTH; + + put_unaligned_le32(req_size, ¶meters->request_length); + + put_unaligned_le32(resp_size, ¶meters->response_length); + + sg_copy_to_buffer(job->request_payload.sg_list, + job->reply_payload.sg_cnt, ¶meters->request, + req_size); + + return smp_buf; +} + +static unsigned int pqi_build_sas_smp_handler_reply( + struct bmic_csmi_smp_passthru_buffer *smp_buf, struct bsg_job *job, + struct pqi_raid_error_info *error_info) +{ + sg_copy_from_buffer(job->reply_payload.sg_list, + job->reply_payload.sg_cnt, &smp_buf->parameters.response, + le32_to_cpu(smp_buf->parameters.response_length)); + + job->reply_len = le16_to_cpu(error_info->sense_data_length); + memcpy(job->reply, error_info->data, + le16_to_cpu(error_info->sense_data_length)); + + return job->reply_payload.payload_len - + get_unaligned_le32(&error_info->data_in_transferred); +} + +void pqi_sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost, + struct sas_rphy *rphy) +{ + int rc; + struct pqi_ctrl_info *ctrl_info = shost_to_hba(shost); + struct bmic_csmi_smp_passthru_buffer *smp_buf; + struct pqi_raid_error_info error_info; + unsigned int reslen = 0; + + pqi_ctrl_busy(ctrl_info); + + if (job->reply_payload.payload_len == 0) { + rc = -ENOMEM; + goto out; + } + + if (!rphy) { + rc = -EINVAL; + goto out; + } + + if (rphy->identify.device_type != SAS_FANOUT_EXPANDER_DEVICE) { + rc = -EINVAL; + goto out; + } + + if (job->request_payload.sg_cnt > 1 || job->reply_payload.sg_cnt > 1) { + rc = -EINVAL; + goto out; + } + + if (pqi_ctrl_offline(ctrl_info)) { + rc = -ENXIO; + goto out; + } + + if (pqi_ctrl_blocked(ctrl_info)) { + rc = -EBUSY; + goto out; + } + + smp_buf = pqi_build_csmi_smp_passthru_buffer(rphy, job); + if (!smp_buf) { + rc = -ENOMEM; + goto out; + } + + rc = pqi_csmi_smp_passthru(ctrl_info, smp_buf, sizeof(*smp_buf), + &error_info); + if (rc) + goto out; + + reslen = pqi_build_sas_smp_handler_reply(smp_buf, job, &error_info); +out: + bsg_job_done(job, rc, reslen); + pqi_ctrl_unbusy(ctrl_info); +} struct sas_function_template pqi_sas_transport_functions = { .get_linkerrors = pqi_sas_get_linkerrors, .get_enclosure_identifier = pqi_sas_get_enclosure_identifier, @@ -338,4 +483,5 @@ struct sas_function_template pqi_sas_transport_functions = { .phy_setup = pqi_sas_phy_setup, .phy_release = pqi_sas_phy_release, .set_phy_speed = pqi_sas_phy_speed, + .smp_handler = pqi_sas_smp_handler, };