From patchwork Fri Feb 24 21:37:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Madhani, Himanshu" X-Patchwork-Id: 9591249 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 49543601AE for ; Fri, 24 Feb 2017 21:38:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 366BC28947 for ; Fri, 24 Feb 2017 21:38:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2B50A28965; Fri, 24 Feb 2017 21:38:37 +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 62F0B28947 for ; Fri, 24 Feb 2017 21:38:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751395AbdBXVie (ORCPT ); Fri, 24 Feb 2017 16:38:34 -0500 Received: from mail-bn3nam01on0088.outbound.protection.outlook.com ([104.47.33.88]:6432 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751273AbdBXViR (ORCPT ); Fri, 24 Feb 2017 16:38:17 -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=zqTrtq4VSxrROvUQa5AqHybsDRxbsD7NgubMf0PjNe8=; b=SqZCTyXAJ6RD5HHIWiwEbMqMLSFfMXXOBprpehSLPnBeJQEKYEHqiuhbNOx68gUWrTbeVbo6EQQDB7bzkjrZ6qcEKJgW8pa5XouZiQNR3M53mrYzgX9R3y7qRuA4xthJ7Abumu11BSVbHXdf+QRmhUYyK/Hv4hSVJMzr89qKL2k= Received: from BY2PR07CA0088.namprd07.prod.outlook.com (10.166.107.41) by BN3PR07MB2626.namprd07.prod.outlook.com (10.167.5.18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.919.13; Fri, 24 Feb 2017 21:37:56 +0000 Received: from BY2FFO11OLC016.protection.gbl (2a01:111:f400:7c0c::111) by BY2PR07CA0088.outlook.office365.com (2a01:111:e400:7bff::41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.888.16 via Frontend Transport; Fri, 24 Feb 2017 21:37:56 +0000 Authentication-Results: spf=none (sender IP is 50.232.66.26) smtp.mailfrom=cavium.com; linux-iscsi.org; dkim=none (message not signed) header.d=none; linux-iscsi.org; dmarc=none action=none header.from=cavium.com; Received-SPF: None (protection.outlook.com: cavium.com does not designate permitted sender hosts) Received: from CAEXCH02.caveonetworks.com (50.232.66.26) by BY2FFO11OLC016.mail.protection.outlook.com (10.1.15.61) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.919.10 via Frontend Transport; Fri, 24 Feb 2017 21:37: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.309.2; Fri, 24 Feb 2017 13:37:45 -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 v1OLbjxG003848; Fri, 24 Feb 2017 13:37:45 -0800 Received: (from root@localhost) by dut1171.mv.qlogic.com (8.14.7/8.14.7/Submit) id v1OLbjm3003847; Fri, 24 Feb 2017 13:37:45 -0800 From: Himanshu Madhani To: , , CC: , , Subject: [PATCH v3 06/14] qla2xxx: Improve T10-DIF/PI handling in driver. Date: Fri, 24 Feb 2017 13:37:35 -0800 Message-ID: <1487972263-3795-7-git-send-email-himanshu.madhani@cavium.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1487972263-3795-1-git-send-email-himanshu.madhani@cavium.com> References: <1487972263-3795-1-git-send-email-himanshu.madhani@cavium.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:50.232.66.26; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(7916002)(39450400003)(2980300002)(428002)(189002)(199003)(5003940100001)(107886003)(38730400002)(626004)(356003)(305945005)(575784001)(92566002)(86362001)(76176999)(50986999)(2201001)(4326007)(36756003)(1691005)(47776003)(2906002)(6666003)(48376002)(80596001)(106466001)(69596002)(33646002)(101416001)(2950100002)(105586002)(42186005)(50466002)(81166006)(54906002)(189998001)(5660300001)(8656002)(50226002)(53946003)(4720700003)(8936002)(8676002)(81156014)(87636001); DIR:OUT; SFP:1101; SCL:1; SRVR:BN3PR07MB2626; H:CAEXCH02.caveonetworks.com; FPR:; SPF:None; PTR:50-232-66-26-static.hfc.comcastbusiness.net; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11OLC016; 1:NsPHaxl/CqC+mO9zvYY3DJGnV0ztAQKovMFPNP4aKx9duQOktd1Vc0m8rk8KoyoPzER39mkcRDO2YULWmjlNRxcwevpunmnzM+5OSn3A/eVDQYKeZ7oFyQf2flSgxYOjXWUJ/ey7F/RHQUkC2JEPv4lemftuIZJssowSF97Vb94aMaB6VEyyQM7Kap3FJW/WJZ1gC5LAjqKwqWFqc6AujGHJYyb+KatsrPu2ARMmo63cByqLuv7KbCWBLdARjNH+sJ9Wljk+paErQwFrYuU1+4I6YyWNMFTUmEp0nOB8Fs5T/tnszCawCbm3UhCSk1NpQ5fHTLXj2l9ax5bB1OheGsdkGwKVjadBDC0Q9wYWuVp9WPJFy3TG29nSBZbhmb/q7jA4CS9VGYiWZmjaBaWX2OAv+nivogzrpVHTrqhzuSVLkulsoV9yfQn72MUhtqX/02ZyMYgzivkrWM9IrQOcM0S7NKweVdE3DfgXJhJQK023aj6Du+tswOey4IE4iQPmHxKzeUB6LYIQPB7edG53sGClNoot1jS3Zb8ARD8cGAU= X-MS-Office365-Filtering-Correlation-Id: a9816209-35d9-40b0-d5b3-08d45cfd65ad X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:BN3PR07MB2626; X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2626; 3:T8mrQiyGWJBrUfSD6WmMb09+CPRy9VHWixIg15j+M7VBAPH7RoY/SxRa7sHKKKnKPA9UyfDJXmdxgjUrjKnwB5JWPoylr+pcte4quwlD2QQlJu0C7NLplfNJZZssfU9sRKb6EI4HLY/JUeCc4nRSBLsY9/p4wxCfUqEnoI/606Qp75AtCQuaZJsa0Ml0jWqkhM068DKpf8wWoSPXpVUx2ya9OIRVZk82fYP4VAhAbIZu2TuiRqcf2lH88V0kpbcFCpEdID2SRHmFDhKEZ7bbugvYN/YZJzC+s0Xm2A2uFzSMtI4WhzqMnpkzMCClW/UvnAeuAXJWFs+OV+AAzm0EyFWDzOnTvF4q3cvM8CPZvKnI3R3Rp+35V53PazuwgXLk; 25:l33t1EW6DY4+o+JgqhwyiCkI+IBWjmdi34AxIOhwm7r+Pc7nGHL77d8ezYI8GzciPg8MNVk2Z9uc6yhJvazF2LOu1gmY6apW9wBKNn9pcEXGgrg/L4RdTH6S2l0qpu7n8bCoGJMUWP46MWrvNIVw80DUvHFptI+5C9Jbn8UpWcTWzQZAYUk4vDpObxUhjh78cpEQhu9fqIM1crU/ofm1xins5Dhg6PC/tRJzFJW25qnqJ652hinSk1XttDsY6Z41QeoMGj9mlsaMWQByqkD8EVdnv4PSsvOUXExmptsVTyyYVITEFDMKgwMFRR5RfEv1u8Ku5b3k0Z6apbjuFpO64p8Fi+gB6ifutakOlkrpF3y39WeqWCmUFv8E7fYLyLybjq5T0Bwcd4GVtBnp0O9+8pTSAMuxm85M49HILzjYjrIr9os+ISqOc060lz8nC7KoILQhDgzFBQvfiFIEvUJdNg== X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2626; 31:b+1AiPsN3xwcLnofcGhy1YX5P/Ym9tFsWLrokoNqK9cz9gz0W01/uSZDgnxtvOftF+FYtvcMUxphs5OwB1NoqAagvELQQsIJ8cC0XMdzGcWgrH3U2FQh3M9ZN6oJRLZRN3fHwvFp8faRlSirEOzg8AMKOSj5aqt4gtP2a0pJMUl8tW6pr2MC3sPAJ/HJB8Fbi+ugsk5ihwU0aZIg7dtkGqyfz9faiXfAGOWGzsYvVZMCHWLK0rcdjGuTuPARdvFN9+HKaxiq9NXbNI52U5QrlUNCz73Zu2egFEoOFgxwCPc=; 20:TsGn+NsMgP6OgJjTPpoVg2j7gC/+ADkCb4oLrMDPQzkm7krX7vcIFxI+rZijdMnXIpOB2Sw3O+PVQKcHPJsXRRp8GvvVJo+LEiN5j4yyPEoQgRa8OAaOTj2z3qFij2tNSE+nYoG2McusKe2tYtbdSY7PPci3wC8M9LAKGCRcbL03DywTAQFnpekNUxgM3WGOXTxjUtDiutrQYvMIq/qiGyxoqYwgdXV6ojCPXFkFb7FjiFYcs2zRngTwBm1i9jVYirTWdX1aAOY7aTDBUOvD0eHyZbQ/TeqM5koujQtgj6QYL6xB/CDljhvgkBwphn2U/3XaNnlAhej4mlRF1q+fuG0EObTx8HQFX2CYfW1OfGfmHWUUKTZDaqYnExs/f/fgzPN8sgYUIzio/PjuJlzxpQxauzEGSu2oXSc0KMYblBr/twPUet9jhmCKon9nAwwyCBWpvwo2xG4h2GHELLzTcUviR8GLlfi8MtAoEb5qG8J7Itz8ICc+dc1ekUNCMJC7 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040375)(601004)(2401047)(13015025)(8121501046)(5005006)(13017025)(13023025)(13024025)(13018025)(10201501046)(3002001)(6041248)(20161123560025)(20161123562025)(20161123564025)(20161123555025)(20161123558025)(6072148); SRVR:BN3PR07MB2626; BCL:0; PCL:0; RULEID:; SRVR:BN3PR07MB2626; X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2626; 4:WijqAai2mns2ADI+pydFBkVR174uYbMpO0afF4eROQHUrnkdcMV6D+1GU0lzeQ3WV+SM6Ffz9ylNiZC7uugZ3hrnMKSAiQVM/XhHmtsQ+0kkiILofNuLD6Vj4jwEblhWwz6CShdotaq8dd59IDOKZNkrQyK1OPzKPoAA7QwhlZ7FB6ggx5wt+dFMXiwaTh3H3gnkhZ74FPAi+MdnFxhtw/rdghXGtyGde5fof4JOGv5R2/rbYknhZsaldUwmtPy4RMTEsC/oAn8P/FAh9UVe/8rOJ9Hxn/fp6ZKiQiBLeD/O1zpd/TQA7EoE7hX6eeXAvz++iUGdCRYWAChyFl5ZsIDYjk5TJ0h37gH6Q8dWAVkjWOYfoiDxoqrxfNL47wPH7IR0zAFx+uR2TJYdLTWeQTjIkZnAwTjLtALt8O45xeGAaGT72AzOiWcKG4hYmhRtythgQPyBsr5JjJCba+yH84aUMhTYZbmgxOeZTPb50XPw4mb9+z0eU6KU0xHlh7Tdwnsmcx4cPZQ0w2F6f5ykmnCj83eq/aeOKLNssGE7Xzxec6gfsGYvYdrc+PpW/4rzk6kARejOzoveU9StUC0gUEOE5zvr0j9fnwTBOGzw2b5QwjCqFtH7XQnwnEFxZ2s229NgQB6Y8a9Xq3Tc2/+XNdpG48JdTeTA8mz/2gJatvpY4C6HQpB9g2LMvnnie2Pt65WLKeXaYFXkzd4krQV6jw== X-Forefront-PRVS: 0228DDDDD7 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BN3PR07MB2626; 23:QkQ8oB0uLe0UWLQbyU84r6GtkkiOj7rj0xCUdtxWn?= =?us-ascii?Q?KVgJH0Zr3/k4j2/wAfSMtJeB/Q6lhhWJ6Wt+vUVpqgMOfgxVrRsKf6tnkIqc?= =?us-ascii?Q?AeChDDIRD+BFiAVRjBpXFhPrhBgxQMSruR+qNtYMSrYCiU2khuXB8eFHsgVr?= =?us-ascii?Q?Zb1pF47rdg4db4YcY/Pvwwy0dVvfJkB3mkXKOSBqonBF4fQ7ZM19T7QMojUm?= =?us-ascii?Q?I66uASY+DGrBK5jRL5L0x1N3U2TYsxKJBvSXTmhqrOmMWkqeimKSK1iLQJQX?= =?us-ascii?Q?l4Qga+1JbOvl0j0xCWRSnc7Ey5Z+hJ5jhPI16+W6DhtCFG/Qj73eOiBJwQMQ?= =?us-ascii?Q?Dkr07bmyr/+v4GoPf3O8J9yA3eCt+uUZKynWl+phE9KZTeJPcqvQW7ITdASS?= =?us-ascii?Q?HHJGPwfBjaeLKe3WDq7LZ6D7E0I7Wa1/g3Cr6UIpMwFLFkjIbrRfumORwlOS?= =?us-ascii?Q?Xo1WUc8dIiLjj8odF2PwUV7ZpplxZfYT0IDvp/7OG+SBg8FzlzwEVzMHdzDU?= =?us-ascii?Q?hG12DawxJmhPHwIht5at3Z0tXlRConyj2hVsup5///7on7A0yNFqKJLGgwCO?= =?us-ascii?Q?7gJZvpzLXpYzmKpgyxuJWkjWqFAFU22qMNpDkRQ/iwcPjiECLk8r6mZL5Pdz?= =?us-ascii?Q?MwS5//VDIjdQEvZKfJX3NNA56cjDfqqs0eT+gbNsS9hl9EimQFVXyJLxHvQ9?= =?us-ascii?Q?eCFbWfb9qLOH5fGZtuXTWqP1nC6GTKMdD7F2df4DBI2S13UjSsH6NOU8LGEO?= =?us-ascii?Q?WrAuoVdCtbMoMbMXdMvovQaNA600WWIHjLAVOMrLn008NXxVE1Oxz52I1+Fm?= =?us-ascii?Q?1IUde7L+pLHE9pHk3wyapWPZOxxJSDX5WwGXJoVRAIfO0sauECsR23KWIVQ+?= =?us-ascii?Q?cfUhgXHw+lJx8UNhEkyWZ/w/4EPuahtMBofMNDny7mGLsVxAmEC1NbrziK03?= =?us-ascii?Q?Hjj7znSRL9YTIWjSdQS2MEiBHRsgbtlX28dv0ZuCMR0LLefW/FQZ+4eLlr95?= =?us-ascii?Q?ncFOS5GIgg0m1F7DUQmPEgDjzOXoXrs1abxZ0NZ3t1rQQPM1A+jkn4IpAHgc?= =?us-ascii?Q?LVf2qunoEFPhg7dhwmvVGxtCNn8516+L60TOJSSWqxgFyNUJAZoaoAX2BMae?= =?us-ascii?Q?BH/io0hNfdFQSr6bOo/tzgPEEkDDcOC?= X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2626; 6:IOLcADosZ499W7St7XZstjGGDIY7GcuLvKYRk6y4gxk0nu0u2n/OHqClL+yirBrwADIjS1QJM6+iUr0NFToJ2MbfPpMt4zElsNdpLN038o/1My9e8fOmWK5RIRammQnBuxJ02agf5FHrZcTPl5LH2MDCX4ERZiDN48ROYeWDXhdwzl5cqnudo+J8BAxT2UZdjn9KThIp8gMpUtJAU5rJof1OvDYF4/wteq+z9GMaGovZmBvCXDmCMfIEjbX4tn2cCj/Tlkqn0stmBk/59iiCOQYVHUFp+O7MdWPXD392FigSPULq2qKchOwW3C60C8skE80ZOciXhEpQmLouNnpBFkTFoOEBjmeFN2YhvGmHVkhga+wLVjE78qUzEfMFTIhcRtGbrkxFnS9vnpwmeg+KNA==; 5:WKdPLAuC6+3YWgXRbxOIyiiEFbBKs4AijwVe7Bdwkj2JU+OZL176QC8ose6xSlcrxaM0iLLnGstL6v+R7AbokJcnB5vIWhukGi0whu3YmClYTftJpWoo9NCz0va2oK24UKoLzF940o5g+mTcE8I7vzCwpyLuLFt8DPObB8Ds5ws=; 24:cr6Clw/JpGPZlkxLqj+Nks2D4SgzzW7NQJ3WJ6DP0q6Tmf7bH0pik2RFvsejRbyka30+ewKzEqJbQ7kABDu0ZsMXv9Khyc+tiDHv/4/c5ms= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2626; 7:N3uMlABlS976gyXv+AcDlf8y1ptei1fPu7ugt8BNchjIxpRJeR5hxSSY+5+5bshF760XxqHdS38a/kbPfcOb85B3hdxELd5lMJ+aEeUcMq5S2QUhJylr++7vkgO9HHDOHNqFMOjOzOH++z329BQTs8M0+KyVxdXkVe8p8YQLR9Okbt9HZipgEfAIG3At4KjG+uy51tuN2BELgBTOgiSMqdy1199+K1C7NM4QH6ekWcElz78LWV70uN0ckdy05Io4AgIQ78NWHQTMRe/wwt2OQwL2kvu55VF3oGZJ9cO+kReAW9McEUKll+68GbZk6R3C1GskZrhoZXjDVt1vo/Ru1A== X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2017 21:37:56.6427 (UTC) 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: BN3PR07MB2626 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 Add routines to support T10 DIF tag. Signed-off-by: Quinn Tran Signed-off-by: Anil Gurumurthy Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_dbg.h | 1 + drivers/scsi/qla2xxx/qla_dfs.c | 8 + drivers/scsi/qla2xxx/qla_target.c | 521 ++++++++++++++++++++++--------------- drivers/scsi/qla2xxx/qla_target.h | 35 ++- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 49 ++-- 5 files changed, 377 insertions(+), 237 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index e1fc4e6..c6bffe9 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -348,6 +348,7 @@ void __attribute__((format (printf, 4, 5))) #define ql_dbg_tgt 0x00004000 /* Target mode */ #define ql_dbg_tgt_mgt 0x00002000 /* Target mode management */ #define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */ +#define ql_dbg_tgt_dif 0x00000800 /* Target mode dif */ extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *, uint32_t, void **); diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index 0fb33e6..dabeb8b 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -360,6 +360,14 @@ goto out; } + ha->tgt.dfs_tgt_port_database = debugfs_create_file("tgt_port_database", + S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_port_database_ops); + if (!ha->tgt.dfs_tgt_port_database) { + ql_log(ql_log_warn, vha, 0xffff, + "Unable to create debugFS tgt_port_database node.\n"); + goto out; + } + ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, vha, &dfs_fce_ops); if (!ha->dfs_fce) { diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 6b60765b5..873cbf7 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -140,6 +140,20 @@ static struct fc_port *qlt_create_sess(struct scsi_qla_host *vha, static DEFINE_MUTEX(qla_tgt_mutex); static LIST_HEAD(qla_tgt_glist); +static const char *prot_op_str(u32 prot_op) +{ + switch (prot_op) { + case TARGET_PROT_NORMAL: return "NORMAL"; + case TARGET_PROT_DIN_INSERT: return "DIN_INSERT"; + case TARGET_PROT_DOUT_INSERT: return "DOUT_INSERT"; + case TARGET_PROT_DIN_STRIP: return "DIN_STRIP"; + case TARGET_PROT_DOUT_STRIP: return "DOUT_STRIP"; + case TARGET_PROT_DIN_PASS: return "DIN_PASS"; + case TARGET_PROT_DOUT_PASS: return "DOUT_PASS"; + default: return "UNKNOWN"; + } +} + /* This API intentionally takes dest as a parameter, rather than returning * int value to avoid caller forgetting to issue wmb() after the store */ void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest) @@ -2018,6 +2032,71 @@ void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd) } EXPORT_SYMBOL(qlt_free_mcmd); +/* + * ha->hardware_lock supposed to be held on entry. Might drop it, then + * reacquire + */ +void qlt_send_resp_ctio(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, + uint8_t scsi_status, uint8_t sense_key, uint8_t asc, uint8_t ascq) +{ + struct atio_from_isp *atio = &cmd->atio; + struct ctio7_to_24xx *ctio; + uint16_t temp; + + ql_dbg(ql_dbg_tgt_dif, vha, 0x3066, + "Sending response CTIO7 (vha=%p, atio=%p, scsi_status=%02x, " + "sense_key=%02x, asc=%02x, ascq=%02x", + vha, atio, scsi_status, sense_key, asc, ascq); + + ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(vha, NULL); + if (!ctio) { + ql_dbg(ql_dbg_async, vha, 0x3067, + "qla2x00t(%ld): %s failed: unable to allocate request packet", + vha->host_no, __func__); + goto out; + } + + ctio->entry_type = CTIO_TYPE7; + ctio->entry_count = 1; + ctio->handle = QLA_TGT_SKIP_HANDLE; + ctio->nport_handle = cmd->sess->loop_id; + ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); + ctio->vp_index = vha->vp_idx; + ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; + ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; + ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; + ctio->exchange_addr = atio->u.isp24.exchange_addr; + ctio->u.status1.flags = (atio->u.isp24.attr << 9) | + cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS); + temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id); + ctio->u.status1.ox_id = cpu_to_le16(temp); + ctio->u.status1.scsi_status = + cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID | scsi_status); + ctio->u.status1.response_len = cpu_to_le16(18); + ctio->u.status1.residual = cpu_to_le32(get_datalen_for_atio(atio)); + + if (ctio->u.status1.residual != 0) + ctio->u.status1.scsi_status |= + cpu_to_le16(SS_RESIDUAL_UNDER); + + /* Response code and sense key */ + put_unaligned_le32(((0x70 << 24) | (sense_key << 8)), + (&ctio->u.status1.sense_data)[0]); + /* Additional sense length */ + put_unaligned_le32(0x0a, + (&ctio->u.status1.sense_data)[1]); + /* ASC and ASCQ */ + put_unaligned_le32(((asc << 24) | (ascq << 16)), + (&ctio->u.status1.sense_data)[3]); + + /* Memory Barrier */ + wmb(); + + qla2x00_start_iocbs(vha, vha->req); +out: + return; +} + /* callback from target fabric module code */ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) { @@ -2268,7 +2347,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm, } else ha->tgt.cmds[h-1] = prm->cmd; - pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK; + pkt->handle = CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = prm->cmd->loop_id; pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; @@ -2396,6 +2475,50 @@ static inline int qlt_has_data(struct qla_tgt_cmd *cmd) return cmd->bufflen > 0; } +static void qlt_print_dif_err(struct qla_tgt_prm *prm) +{ + struct qla_tgt_cmd *cmd; + struct scsi_qla_host *vha; + + /* asc 0x10=dif error */ + if (prm->sense_buffer && (prm->sense_buffer[12] == 0x10)) { + cmd = prm->cmd; + vha = cmd->vha; + /* ASCQ */ + switch (prm->sense_buffer[13]) { + case 1: + ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + "BE detected Guard TAG ERR: lba[0x%llx|%lld] len[0x%x] " + "se_cmd=%p tag[%x]", + cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd, + cmd->atio.u.isp24.exchange_addr); + break; + case 2: + ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + "BE detected APP TAG ERR: lba[0x%llx|%lld] len[0x%x] " + "se_cmd=%p tag[%x]", + cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd, + cmd->atio.u.isp24.exchange_addr); + break; + case 3: + ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + "BE detected REF TAG ERR: lba[0x%llx|%lld] len[0x%x] " + "se_cmd=%p tag[%x]", + cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd, + cmd->atio.u.isp24.exchange_addr); + break; + default: + ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + "BE detected Dif ERR: lba[%llx|%lld] len[%x] " + "se_cmd=%p tag[%x]", + cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd, + cmd->atio.u.isp24.exchange_addr); + break; + } + ql_dump_buffer(ql_dbg_tgt_dif, vha, 0xffff, cmd->cdb, 16); + } +} + /* * Called without ha->hardware_lock held */ @@ -2517,18 +2640,9 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, for (i = 0; i < prm->sense_buffer_len/4; i++) ((uint32_t *)ctio->u.status1.sense_data)[i] = cpu_to_be32(((uint32_t *)prm->sense_buffer)[i]); -#if 0 - if (unlikely((prm->sense_buffer_len % 4) != 0)) { - static int q; - if (q < 10) { - ql_dbg(ql_dbg_tgt, vha, 0xe04f, - "qla_target(%d): %d bytes of sense " - "lost", prm->tgt->ha->vp_idx, - prm->sense_buffer_len % 4); - q++; - } - } -#endif + + qlt_print_dif_err(prm); + } else { ctio->u.status1.flags &= ~cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0); @@ -2542,19 +2656,9 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, /* Sense with len > 24, is it possible ??? */ } - - -/* diff */ static inline int qlt_hba_err_chk_enabled(struct se_cmd *se_cmd) { - /* - * Uncomment when corresponding SCSI changes are done. - * - if (!sp->cmd->prot_chk) - return 0; - * - */ switch (se_cmd->prot_op) { case TARGET_PROT_DOUT_INSERT: case TARGET_PROT_DIN_STRIP: @@ -2575,16 +2679,37 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, return 0; } +static inline int +qla_tgt_ref_mask_check(struct se_cmd *se_cmd) +{ + switch (se_cmd->prot_op) { + case TARGET_PROT_DIN_INSERT: + case TARGET_PROT_DOUT_INSERT: + case TARGET_PROT_DIN_STRIP: + case TARGET_PROT_DOUT_STRIP: + case TARGET_PROT_DIN_PASS: + case TARGET_PROT_DOUT_PASS: + return 1; + default: + return 0; + } +} + /* - * qla24xx_set_t10dif_tags_from_cmd - Extract Ref and App tags from SCSI command - * + * qla_tgt_set_dif_tags - Extract Ref and App tags from SCSI command */ -static inline void -qlt_set_t10dif_tags(struct se_cmd *se_cmd, struct crc_context *ctx) +static void +qla_tgt_set_dif_tags(struct qla_tgt_cmd *cmd, struct crc_context *ctx, + uint16_t *pfw_prot_opts) { + struct se_cmd *se_cmd = &cmd->se_cmd; uint32_t lba = 0xffffffff & se_cmd->t_task_lba; + scsi_qla_host_t *vha = cmd->tgt->vha; + struct qla_hw_data *ha = vha->hw; + uint32_t t32 = 0; - /* wait til Mode Sense/Select cmd, modepage Ah, subpage 2 + /* + * wait till Mode Sense/Select cmd, modepage Ah, subpage 2 * have been immplemented by TCM, before AppTag is avail. * Look for modesense_handlers[] */ @@ -2592,65 +2717,73 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, ctx->app_tag_mask[0] = 0x0; ctx->app_tag_mask[1] = 0x0; + if (IS_PI_UNINIT_CAPABLE(ha)) { + if ((se_cmd->prot_type == TARGET_DIF_TYPE1_PROT) || + (se_cmd->prot_type == TARGET_DIF_TYPE2_PROT)) + *pfw_prot_opts |= PO_DIS_VALD_APP_ESC; + else if (se_cmd->prot_type == TARGET_DIF_TYPE3_PROT) + *pfw_prot_opts |= PO_DIS_VALD_APP_REF_ESC; + } + + t32 = ha->tgt.tgt_ops->get_dif_tags(cmd, pfw_prot_opts); + switch (se_cmd->prot_type) { case TARGET_DIF_TYPE0_PROT: /* - * No check for ql2xenablehba_err_chk, as it would be an - * I/O error if hba tag generation is not done. + * No check for ql2xenablehba_err_chk, as it + * would be an I/O error if hba tag generation + * is not done. */ ctx->ref_tag = cpu_to_le32(lba); - - if (!qlt_hba_err_chk_enabled(se_cmd)) - break; - /* enable ALL bytes of the ref tag */ ctx->ref_tag_mask[0] = 0xff; ctx->ref_tag_mask[1] = 0xff; ctx->ref_tag_mask[2] = 0xff; ctx->ref_tag_mask[3] = 0xff; break; - /* - * For TYpe 1 protection: 16 bit GUARD tag, 32 bit REF tag, and - * 16 bit app tag. - */ case TARGET_DIF_TYPE1_PROT: - ctx->ref_tag = cpu_to_le32(lba); - - if (!qlt_hba_err_chk_enabled(se_cmd)) - break; - - /* enable ALL bytes of the ref tag */ - ctx->ref_tag_mask[0] = 0xff; - ctx->ref_tag_mask[1] = 0xff; - ctx->ref_tag_mask[2] = 0xff; - ctx->ref_tag_mask[3] = 0xff; - break; - /* - * For TYPE 2 protection: 16 bit GUARD + 32 bit REF tag has to - * match LBA in CDB + N - */ + /* + * For TYPE 1 protection: 16 bit GUARD tag, 32 bit + * REF tag, and 16 bit app tag. + */ + ctx->ref_tag = cpu_to_le32(lba); + if (!qla_tgt_ref_mask_check(se_cmd) || + !(ha->tgt.tgt_ops->chk_dif_tags(t32))) { + *pfw_prot_opts |= PO_DIS_REF_TAG_VALD; + break; + } + /* enable ALL bytes of the ref tag */ + ctx->ref_tag_mask[0] = 0xff; + ctx->ref_tag_mask[1] = 0xff; + ctx->ref_tag_mask[2] = 0xff; + ctx->ref_tag_mask[3] = 0xff; + break; case TARGET_DIF_TYPE2_PROT: - ctx->ref_tag = cpu_to_le32(lba); - - if (!qlt_hba_err_chk_enabled(se_cmd)) - break; - - /* enable ALL bytes of the ref tag */ - ctx->ref_tag_mask[0] = 0xff; - ctx->ref_tag_mask[1] = 0xff; - ctx->ref_tag_mask[2] = 0xff; - ctx->ref_tag_mask[3] = 0xff; - break; - - /* For Type 3 protection: 16 bit GUARD only */ + /* + * For TYPE 2 protection: 16 bit GUARD + 32 bit REF + * tag has to match LBA in CDB + N + */ + ctx->ref_tag = cpu_to_le32(lba); + if (!qla_tgt_ref_mask_check(se_cmd) || + !(ha->tgt.tgt_ops->chk_dif_tags(t32))) { + *pfw_prot_opts |= PO_DIS_REF_TAG_VALD; + break; + } + /* enable ALL bytes of the ref tag */ + ctx->ref_tag_mask[0] = 0xff; + ctx->ref_tag_mask[1] = 0xff; + ctx->ref_tag_mask[2] = 0xff; + ctx->ref_tag_mask[3] = 0xff; + break; case TARGET_DIF_TYPE3_PROT: - ctx->ref_tag_mask[0] = ctx->ref_tag_mask[1] = - ctx->ref_tag_mask[2] = ctx->ref_tag_mask[3] = 0x00; - break; + /* For TYPE 3 protection: 16 bit GUARD only */ + *pfw_prot_opts |= PO_DIS_REF_TAG_VALD; + ctx->ref_tag_mask[0] = ctx->ref_tag_mask[1] = + ctx->ref_tag_mask[2] = ctx->ref_tag_mask[3] = 0x00; + break; } } - static inline int qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) { @@ -2696,14 +2829,12 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, transfer_length = data_bytes; data_bytes += dif_bytes; break; - case TARGET_PROT_DIN_STRIP: case TARGET_PROT_DOUT_INSERT: case TARGET_PROT_DIN_PASS: case TARGET_PROT_DOUT_PASS: transfer_length = data_bytes + dif_bytes; break; - default: BUG(); break; @@ -2739,7 +2870,6 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, break; } - /* ---- PKT ---- */ /* Update entry type to indicate Command Type CRC_2 IOCB */ pkt->entry_type = CTIO_CRC2; @@ -2757,7 +2887,6 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, } else ha->tgt.cmds[h-1] = prm->cmd; - pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = prm->cmd->loop_id; pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); @@ -2780,12 +2909,10 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, else if (cmd->dma_data_direction == DMA_FROM_DEVICE) pkt->flags = cpu_to_le16(CTIO7_FLAGS_DATA_OUT); - pkt->dseg_count = prm->tot_dsds; /* Fibre channel byte count */ pkt->transfer_length = cpu_to_le32(transfer_length); - /* ----- CRC context -------- */ /* Allocate CRC context from global pool */ @@ -2805,13 +2932,12 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, /* Set handle */ crc_ctx_pkt->handle = pkt->handle; - qlt_set_t10dif_tags(se_cmd, crc_ctx_pkt); + qla_tgt_set_dif_tags(cmd, crc_ctx_pkt, &fw_prot_opts); pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma)); pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma)); pkt->crc_context_len = CRC_CONTEXT_LEN_FW; - if (!bundling) { cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address; } else { @@ -2832,7 +2958,6 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes); crc_ctx_pkt->guard_seed = cpu_to_le16(0); - /* Walks data segments */ pkt->flags |= cpu_to_le16(CTIO7_FLAGS_DSD_PTR); @@ -2857,11 +2982,9 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, crc_queuing_error: /* Cleanup will be performed by the caller */ - return QLA_FUNCTION_FAILED; } - /* * Callback to setup response of xmit_type of QLA_TGT_XMIT_DATA and * * QLA_TGT_XMIT_STATUS for >= 24xx silicon @@ -3109,139 +3232,113 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) /* - * Checks the guard or meta-data for the type of error - * detected by the HBA. + * it is assumed either hardware_lock or qpair lock is held. */ -static inline int +static void qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, - struct ctio_crc_from_fw *sts) + struct ctio_crc_from_fw *sts) { uint8_t *ap = &sts->actual_dif[0]; uint8_t *ep = &sts->expected_dif[0]; - uint32_t e_ref_tag, a_ref_tag; - uint16_t e_app_tag, a_app_tag; - uint16_t e_guard, a_guard; uint64_t lba = cmd->se_cmd.t_task_lba; + uint8_t scsi_status, sense_key, asc, ascq; + unsigned long flags; - a_guard = be16_to_cpu(*(uint16_t *)(ap + 0)); - a_app_tag = be16_to_cpu(*(uint16_t *)(ap + 2)); - a_ref_tag = be32_to_cpu(*(uint32_t *)(ap + 4)); - - e_guard = be16_to_cpu(*(uint16_t *)(ep + 0)); - e_app_tag = be16_to_cpu(*(uint16_t *)(ep + 2)); - e_ref_tag = be32_to_cpu(*(uint32_t *)(ep + 4)); - - ql_dbg(ql_dbg_tgt, vha, 0xe075, - "iocb(s) %p Returned STATUS.\n", sts); - - ql_dbg(ql_dbg_tgt, vha, 0xf075, - "dif check TGT cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x]\n", - cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba, - a_ref_tag, e_ref_tag, a_app_tag, e_app_tag, a_guard, e_guard); - - /* - * Ignore sector if: - * For type 3: ref & app tag is all 'f's - * For type 0,1,2: app tag is all 'f's - */ - if ((a_app_tag == 0xffff) && - ((cmd->se_cmd.prot_type != TARGET_DIF_TYPE3_PROT) || - (a_ref_tag == 0xffffffff))) { - uint32_t blocks_done; - - /* 2TB boundary case covered automatically with this */ - blocks_done = e_ref_tag - (uint32_t)lba + 1; - cmd->se_cmd.bad_sector = e_ref_tag; - cmd->se_cmd.pi_err = 0; - ql_dbg(ql_dbg_tgt, vha, 0xf074, - "need to return scsi good\n"); - - /* Update protection tag */ - if (cmd->prot_sg_cnt) { - uint32_t i, k = 0, num_ent; - struct scatterlist *sg, *sgl; - + cmd->trc_flags |= TRC_DIF_ERR; - sgl = cmd->prot_sg; + cmd->a_guard = be16_to_cpu(*(uint16_t *)(ap + 0)); + cmd->a_app_tag = be16_to_cpu(*(uint16_t *)(ap + 2)); + cmd->a_ref_tag = be32_to_cpu(*(uint32_t *)(ap + 4)); - /* Patch the corresponding protection tags */ - for_each_sg(sgl, sg, cmd->prot_sg_cnt, i) { - num_ent = sg_dma_len(sg) / 8; - if (k + num_ent < blocks_done) { - k += num_ent; - continue; - } - k = blocks_done; - break; - } + cmd->e_guard = be16_to_cpu(*(uint16_t *)(ep + 0)); + cmd->e_app_tag = be16_to_cpu(*(uint16_t *)(ep + 2)); + cmd->e_ref_tag = be32_to_cpu(*(uint32_t *)(ep + 4)); - if (k != blocks_done) { - ql_log(ql_log_warn, vha, 0xf076, - "unexpected tag values tag:lba=%u:%llu)\n", - e_ref_tag, (unsigned long long)lba); - goto out; - } + ql_dbg(ql_dbg_tgt_dif, vha, 0xf075, + "%s: aborted %d state %d\n", __func__, cmd->aborted, cmd->state); -#if 0 - struct sd_dif_tuple *spt; - /* TODO: - * This section came from initiator. Is it valid here? - * should ulp be override with actual val??? - */ - spt = page_address(sg_page(sg)) + sg->offset; - spt += j; + scsi_status = sense_key = asc = ascq = 0; - spt->app_tag = 0xffff; - if (cmd->se_cmd.prot_type == SCSI_PROT_DIF_TYPE3) - spt->ref_tag = 0xffffffff; -#endif - } - - return 0; - } - - /* check guard */ - if (e_guard != a_guard) { - cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED; - cmd->se_cmd.bad_sector = cmd->se_cmd.t_task_lba; - - ql_log(ql_log_warn, vha, 0xe076, - "Guard ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n", - cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba, - a_ref_tag, e_ref_tag, a_app_tag, e_app_tag, - a_guard, e_guard, cmd); - goto out; + /* check appl tag */ + if (cmd->e_app_tag != cmd->a_app_tag) { + ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + "App Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] " + "Ref[%x|%x], App[%x|%x], " + "Guard [%x|%x] cmd=%p ox_id[%04x]", + cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks, + cmd->a_ref_tag, cmd->e_ref_tag, + cmd->a_app_tag, cmd->e_app_tag, + cmd->a_guard, cmd->e_guard, + cmd, cmd->atio.u.isp24.fcp_hdr.ox_id); + + cmd->dif_err_code = DIF_ERR_APP; + scsi_status = SAM_STAT_CHECK_CONDITION; + sense_key = ABORTED_COMMAND; + asc = 0x10; + ascq = 0x2; } /* check ref tag */ - if (e_ref_tag != a_ref_tag) { - cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED; - cmd->se_cmd.bad_sector = e_ref_tag; - - ql_log(ql_log_warn, vha, 0xe077, - "Ref Tag ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n", - cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba, - a_ref_tag, e_ref_tag, a_app_tag, e_app_tag, - a_guard, e_guard, cmd); + if (cmd->e_ref_tag != cmd->a_ref_tag) { + ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + "Ref Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] " + "Ref[%x|%x], App[%x|%x], " + "Guard[%x|%x] cmd=%p ox_id[%04x] ", + cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks, + cmd->a_ref_tag, cmd->e_ref_tag, + cmd->a_app_tag, cmd->e_app_tag, + cmd->a_guard, cmd->e_guard, + cmd, cmd->atio.u.isp24.fcp_hdr.ox_id); + + cmd->dif_err_code = DIF_ERR_REF; + scsi_status = SAM_STAT_CHECK_CONDITION; + sense_key = ABORTED_COMMAND; + asc = 0x10; + ascq = 0x3; goto out; } - /* check appl tag */ - if (e_app_tag != a_app_tag) { - cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED; - cmd->se_cmd.bad_sector = cmd->se_cmd.t_task_lba; - - ql_log(ql_log_warn, vha, 0xe078, - "App Tag ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n", - cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba, - a_ref_tag, e_ref_tag, a_app_tag, e_app_tag, - a_guard, e_guard, cmd); - goto out; + /* check guard */ + if (cmd->e_guard != cmd->a_guard) { + ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + "Guard ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] " + "Ref[%x|%x], App[%x|%x], " + "Guard [%x|%x] cmd=%p ox_id[%04x]", + cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks, + cmd->a_ref_tag, cmd->e_ref_tag, + cmd->a_app_tag, cmd->e_app_tag, + cmd->a_guard, cmd->e_guard, + cmd, cmd->atio.u.isp24.fcp_hdr.ox_id); + cmd->dif_err_code = DIF_ERR_GRD; + scsi_status = SAM_STAT_CHECK_CONDITION; + sense_key = ABORTED_COMMAND; + asc = 0x10; + ascq = 0x1; } out: - return 1; -} + switch (cmd->state) { + case QLA_TGT_STATE_NEED_DATA: + /* handle_data will load DIF error code */ + cmd->state = QLA_TGT_STATE_DATA_IN; + vha->hw->tgt.tgt_ops->handle_data(cmd); + break; + default: + spin_lock_irqsave(&cmd->cmd_lock, flags); + if (cmd->aborted) { + spin_unlock_irqrestore(&cmd->cmd_lock, flags); + vha->hw->tgt.tgt_ops->free_cmd(cmd); + break; + } + spin_unlock_irqrestore(&cmd->cmd_lock, flags); + qlt_send_resp_ctio(vha, cmd, scsi_status, sense_key, asc, ascq); + /* assume scsi status gets out on the wire. + * Will not wait for completion. + */ + vha->hw->tgt.tgt_ops->free_cmd(cmd); + break; + } +} /* If hardware_lock held on entry, might drop it, then reaquire */ /* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ @@ -3548,6 +3645,16 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio, { int term = 0; + if (cmd->se_cmd.prot_op) + ql_dbg(ql_dbg_tgt_dif, vha, 0xffff, + "Term DIF cmd: lba[0x%llx|%lld] len[0x%x] " + "se_cmd=%p tag[%x] op %#x/%s", + cmd->lba, cmd->lba, + cmd->num_blks, &cmd->se_cmd, + cmd->atio.u.isp24.exchange_addr, + cmd->se_cmd.prot_op, + prot_op_str(cmd->se_cmd.prot_op)); + if (ctio != NULL) { struct ctio7_from_24xx *c = (struct ctio7_from_24xx *)ctio; term = !(c->flags & @@ -3765,32 +3872,15 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, struct ctio_crc_from_fw *crc = (struct ctio_crc_from_fw *)ctio; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf073, - "qla_target(%d): CTIO with DIF_ERROR status %x received (state %x, se_cmd %p) actual_dif[0x%llx] expect_dif[0x%llx]\n", + "qla_target(%d): CTIO with DIF_ERROR status %x " + "received (state %x, ulp_cmd %p) actual_dif[0x%llx] " + "expect_dif[0x%llx]\n", vha->vp_idx, status, cmd->state, se_cmd, *((u64 *)&crc->actual_dif[0]), *((u64 *)&crc->expected_dif[0])); - if (qlt_handle_dif_error(vha, cmd, ctio)) { - if (cmd->state == QLA_TGT_STATE_NEED_DATA) { - /* scsi Write/xfer rdy complete */ - goto skip_term; - } else { - /* scsi read/xmit respond complete - * call handle dif to send scsi status - * rather than terminate exchange. - */ - cmd->state = QLA_TGT_STATE_PROCESSED; - ha->tgt.tgt_ops->handle_dif_err(cmd); - return; - } - } else { - /* Need to generate a SCSI good completion. - * because FW did not send scsi status. - */ - status = 0; - goto skip_term; - } - break; + qlt_handle_dif_error(vha, cmd, ctio); + return; } default: ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b, @@ -3813,7 +3903,6 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, return; } } -skip_term: if (cmd->state == QLA_TGT_STATE_PROCESSED) { cmd->trc_flags |= TRC_CTIO_DONE; diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index a7f90dc..c73c938 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -378,6 +378,14 @@ static inline void adjust_corrupted_atio(struct atio_from_isp *atio) atio->u.isp24.fcp_cmnd.add_cdb_len = 0; } +static inline int get_datalen_for_atio(struct atio_from_isp *atio) +{ + int len = atio->u.isp24.fcp_cmnd.add_cdb_len; + + return (be32_to_cpu(get_unaligned((uint32_t *) + &atio->u.isp24.fcp_cmnd.add_cdb[len * 4]))); +} + #define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */ /* @@ -667,7 +675,6 @@ struct qla_tgt_func_tmpl { int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *, unsigned char *, uint32_t, int, int, int); void (*handle_data)(struct qla_tgt_cmd *); - void (*handle_dif_err)(struct qla_tgt_cmd *); int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint16_t, uint32_t); void (*free_cmd)(struct qla_tgt_cmd *); @@ -684,6 +691,8 @@ struct qla_tgt_func_tmpl { void (*clear_nacl_from_fcport_map)(struct fc_port *); void (*put_sess)(struct fc_port *); void (*shutdown_sess)(struct fc_port *); + int (*get_dif_tags)(struct qla_tgt_cmd *cmd, uint16_t *pfw_prot_opts); + int (*chk_dif_tags)(uint32_t tag); }; int qla2x00_wait_for_hba_online(struct scsi_qla_host *); @@ -720,8 +729,8 @@ struct qla_tgt_func_tmpl { #define QLA_TGT_ABORT_ALL 0xFFFE #define QLA_TGT_NEXUS_LOSS_SESS 0xFFFD #define QLA_TGT_NEXUS_LOSS 0xFFFC -#define QLA_TGT_ABTS 0xFFFB -#define QLA_TGT_2G_ABORT_TASK 0xFFFA +#define QLA_TGT_ABTS 0xFFFB +#define QLA_TGT_2G_ABORT_TASK 0xFFFA /* Notify Acknowledge flags */ #define NOTIFY_ACK_RES_COUNT BIT_8 @@ -845,6 +854,7 @@ enum trace_flags { TRC_CMD_FREE = BIT_17, TRC_DATA_IN = BIT_18, TRC_ABORT = BIT_19, + TRC_DIF_ERR = BIT_20, }; struct qla_tgt_cmd { @@ -885,11 +895,23 @@ struct qla_tgt_cmd { struct list_head cmd_list; struct atio_from_isp atio; - /* t10dif */ + + /* T10-DIF */ +#define DIF_ERR_NONE 0 +#define DIF_ERR_GRD 1 +#define DIF_ERR_REF 2 +#define DIF_ERR_APP 3 + int8_t dif_err_code; struct scatterlist *prot_sg; uint32_t prot_sg_cnt; - uint32_t blk_sz; + uint32_t blk_sz, num_blks; + uint8_t scsi_status, sense_key, asc, ascq; + struct crc_context *ctx; + uint8_t *cdb; + uint64_t lba; + uint16_t a_guard, e_guard, a_app_tag, e_app_tag; + uint32_t a_ref_tag, e_ref_tag; uint64_t jiffies_at_alloc; uint64_t jiffies_at_free; @@ -1053,4 +1075,7 @@ extern void qlt_modify_vp_config(struct scsi_qla_host *, extern void qlt_logo_completion_handler(fc_port_t *, int); extern void qlt_do_generation_tick(struct scsi_qla_host *, int *); +void qlt_send_resp_ctio(scsi_qla_host_t *, struct qla_tgt_cmd *, uint8_t, + uint8_t, uint8_t, uint8_t); + #endif /* __QLA_TARGET_H */ diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index c2f8c35..1d5ed79 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -531,6 +531,24 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work) return; } + switch (cmd->dif_err_code) { + case DIF_ERR_GRD: + cmd->se_cmd.pi_err = + TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED; + break; + case DIF_ERR_REF: + cmd->se_cmd.pi_err = + TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED; + break; + case DIF_ERR_APP: + cmd->se_cmd.pi_err = + TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED; + break; + case DIF_ERR_NONE: + default: + break; + } + if (cmd->se_cmd.pi_err) transport_generic_request_failure(&cmd->se_cmd, cmd->se_cmd.pi_err); @@ -555,25 +573,23 @@ static void tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd) queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work); } -static void tcm_qla2xxx_handle_dif_work(struct work_struct *work) +static int tcm_qla2xxx_chk_dif_tags(uint32_t tag) { - struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); - - /* take an extra kref to prevent cmd free too early. - * need to wait for SCSI status/check condition to - * finish responding generate by transport_generic_request_failure. - */ - kref_get(&cmd->se_cmd.cmd_kref); - transport_generic_request_failure(&cmd->se_cmd, cmd->se_cmd.pi_err); + return 0; } -/* - * Called from qla_target.c:qlt_do_ctio_completion() - */ -static void tcm_qla2xxx_handle_dif_err(struct qla_tgt_cmd *cmd) +static int tcm_qla2xxx_dif_tags(struct qla_tgt_cmd *cmd, + uint16_t *pfw_prot_opts) { - INIT_WORK(&cmd->work, tcm_qla2xxx_handle_dif_work); - queue_work(tcm_qla2xxx_free_wq, &cmd->work); + struct se_cmd *se_cmd = &cmd->se_cmd; + + if (!(se_cmd->prot_checks & TARGET_DIF_CHECK_GUARD)) + *pfw_prot_opts |= PO_DISABLE_GUARD_CHECK; + + if (!(se_cmd->prot_checks & TARGET_DIF_CHECK_APPTAG)) + *pfw_prot_opts |= PO_DIS_APP_TAG_VALD; + + return 0; } /* @@ -1610,7 +1626,6 @@ static void tcm_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id, static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { .handle_cmd = tcm_qla2xxx_handle_cmd, .handle_data = tcm_qla2xxx_handle_data, - .handle_dif_err = tcm_qla2xxx_handle_dif_err, .handle_tmr = tcm_qla2xxx_handle_tmr, .free_cmd = tcm_qla2xxx_free_cmd, .free_mcmd = tcm_qla2xxx_free_mcmd, @@ -1622,6 +1637,8 @@ static void tcm_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id, .clear_nacl_from_fcport_map = tcm_qla2xxx_clear_nacl_from_fcport_map, .put_sess = tcm_qla2xxx_put_sess, .shutdown_sess = tcm_qla2xxx_shutdown_sess, + .get_dif_tags = tcm_qla2xxx_dif_tags, + .chk_dif_tags = tcm_qla2xxx_chk_dif_tags, }; static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport)