From patchwork Thu Mar 9 21:54:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 661480 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BA922C6FD19 for ; Thu, 9 Mar 2023 21:55:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230044AbjCIVzc (ORCPT ); Thu, 9 Mar 2023 16:55:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229827AbjCIVz3 (ORCPT ); Thu, 9 Mar 2023 16:55:29 -0500 Received: from esa6.hgst.iphmx.com (esa6.hgst.iphmx.com [216.71.154.45]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 54567EFF56; Thu, 9 Mar 2023 13:55:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1678398928; x=1709934928; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1Zry+xIqYFsz3JgSeEtU4aVUlj69W599ZfDPhMsvGkY=; b=T5DqoNQO6N0J3w5XNU8/wbHyheUzl4DroKizwfptYVpGoE+Y3TeFZoJj nX2Gfov8no7mEXJy8O+13jBFF4mPWbfD87gKlB+qu2kGmu+vkS0Rr2TO5 NuW5l27PPgcSGSwcwuds9Oiuv4+vXdIqWYF84TCP+cYEoa2Z8bIZyw4Na ER9t7APGg+VGYHgfHmPW1xgaeYwozAugp3ysuQeV48idTDd+05xAlUvRm 4K9G+jnWuJiwq0suAHYyogNgCUnuBaO9VNgdt/+Soov0PfeOeiXmWNqSN w1mOEjGKrjtmR+Zj5Lr9lFG73o80QKs7rRKDqY1cYOzOXyvbgDLsU5gKi A==; X-IronPort-AV: E=Sophos;i="5.98,247,1673884800"; d="scan'208";a="225270940" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 10 Mar 2023 05:55:28 +0800 IronPort-SDR: VVbJiTIdM9vIQ/kK+wllKsZ/y5gh1stwbdcSWWMsTK+dHdLeY4Tpt33hXiDPY/JP28671q1IZr tNcD1wReMO2kXUo23TanelEX+9faG4ae6BOGNkED9K98ZaYt9qiUJ/PWGjhD3CQg612nfgFivb HkRBS4n4jlzpEARvP7GvpvLb4g+iH0qKAOqJlrn89LyrG8O3cGJj62iFpcmx5WHONlus0Bg3G7 OFvHI/GfXAWBUfKBqIPTnapkqY2B/PbbypaTqzILEfUTGGK1clqA4dl9QlY2afVBAW+4wEyr7d 8yk= Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 09 Mar 2023 13:06:21 -0800 IronPort-SDR: Jjcbd6yG/XIPTYDwnd/aqeqqms583YFh60V6QSRq8tsGNVFDgbyRhAdVhp7peXPfsFvO9pW4fA wAb0PUZaQSd5W9R6+b5u3xA9mbtDdjtYTFqHzJC7jBzpHpAfb7kbmNZsAZDYNaGhoyUMLqHMao kgWy2FJbxIeJO19ZkG/MHEoL3Mctij0fw6WgimsCyDGcXXNoOa44e3ky2uOLxvEktqQhMIyLks B/DjA+cKAowfk5VMGgdE0qLi72WCWqnc13eFPPFPlUrJvBUg7b28T8rrK30A9WxY0pSJr59YOO EG0= WDCIronportException: Internal Received: from unknown (HELO x1-carbon.wdc.com) ([10.225.164.41]) by uls-op-cesaip01.wdc.com with ESMTP; 09 Mar 2023 13:55:26 -0800 From: Niklas Cassel To: Paolo Valente , Jens Axboe Cc: Christoph Hellwig , Hannes Reinecke , Damien Le Moal , linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, linux-block@vger.kernel.org, Niklas Cassel Subject: [PATCH v4 01/19] ioprio: cleanup interface definition Date: Thu, 9 Mar 2023 22:54:53 +0100 Message-Id: <20230309215516.3800571-2-niklas.cassel@wdc.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230309215516.3800571-1-niklas.cassel@wdc.com> References: <20230309215516.3800571-1-niklas.cassel@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Damien Le Moal The IO priority user interface defines the 16-bits ioprio values as the combination of the upper 3-bits for an IO priority class and the lower 13-bits as priority data. However, the kernel only uses the lower 3-bits of the priority data to define priority levels for the RT and BE priority classes. The data part of an ioprio value is completely ignored for the IDLE and NONE classes. This is enforced by checks done in ioprio_check_cap(), which is called for all paths that allow defining an IO priority for IOs: the per-context ioprio_set() system call, aio interface and io-uring interface. Clarify this fact in the uapi ioprio.h header file and introduce the IOPRIO_PRIO_LEVEL_MASK and IOPRIO_PRIO_LEVEL() macros for users to define and get priority levels in an ioprio value. The coarser macro IOPRIO_PRIO_DATA() is retained for backward compatibility with old applications already using it. There is no functional change introduced with this. In-kernel users of the IOPRIO_PRIO_DATA() macro which are explicitly handling IO priority data as a priority level are modified to use the new IOPRIO_PRIO_LEVEL() macro without any functional change. Since f2fs is the only user of this macro not explicitly using that value as a priority level, it is left unchanged. Signed-off-by: Damien Le Moal Signed-off-by: Niklas Cassel --- block/bfq-iosched.c | 8 ++++---- block/ioprio.c | 6 +++--- include/uapi/linux/ioprio.h | 19 ++++++++++++++----- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 8a8d4441519c..e4ca0a3483d3 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -5523,16 +5523,16 @@ bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) bfqq->new_ioprio_class = task_nice_ioclass(tsk); break; case IOPRIO_CLASS_RT: - bfqq->new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + bfqq->new_ioprio = IOPRIO_PRIO_LEVEL(bic->ioprio); bfqq->new_ioprio_class = IOPRIO_CLASS_RT; break; case IOPRIO_CLASS_BE: - bfqq->new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + bfqq->new_ioprio = IOPRIO_PRIO_LEVEL(bic->ioprio); bfqq->new_ioprio_class = IOPRIO_CLASS_BE; break; case IOPRIO_CLASS_IDLE: bfqq->new_ioprio_class = IOPRIO_CLASS_IDLE; - bfqq->new_ioprio = 7; + bfqq->new_ioprio = IOPRIO_NR_LEVELS - 1; break; } @@ -5829,7 +5829,7 @@ static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, struct bfq_io_cq *bic, bool respawn) { - const int ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + const int ioprio = IOPRIO_PRIO_LEVEL(bic->ioprio); const int ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); struct bfq_queue **async_bfqq = NULL; struct bfq_queue *bfqq; diff --git a/block/ioprio.c b/block/ioprio.c index 32a456b45804..f0d9e818abc5 100644 --- a/block/ioprio.c +++ b/block/ioprio.c @@ -33,7 +33,7 @@ int ioprio_check_cap(int ioprio) { int class = IOPRIO_PRIO_CLASS(ioprio); - int data = IOPRIO_PRIO_DATA(ioprio); + int level = IOPRIO_PRIO_LEVEL(ioprio); switch (class) { case IOPRIO_CLASS_RT: @@ -49,13 +49,13 @@ int ioprio_check_cap(int ioprio) fallthrough; /* rt has prio field too */ case IOPRIO_CLASS_BE: - if (data >= IOPRIO_NR_LEVELS || data < 0) + if (level >= IOPRIO_NR_LEVELS) return -EINVAL; break; case IOPRIO_CLASS_IDLE: break; case IOPRIO_CLASS_NONE: - if (data) + if (level) return -EINVAL; break; default: diff --git a/include/uapi/linux/ioprio.h b/include/uapi/linux/ioprio.h index f70f2596a6bf..4444b4e4fdad 100644 --- a/include/uapi/linux/ioprio.h +++ b/include/uapi/linux/ioprio.h @@ -17,7 +17,7 @@ ((data) & IOPRIO_PRIO_MASK)) /* - * These are the io priority groups as implemented by the BFQ and mq-deadline + * These are the io priority classes as implemented by the BFQ and mq-deadline * schedulers. RT is the realtime class, it always gets premium service. For * ATA disks supporting NCQ IO priority, RT class IOs will be processed using * high priority NCQ commands. BE is the best-effort scheduling class, the @@ -32,11 +32,20 @@ enum { }; /* - * The RT and BE priority classes both support up to 8 priority levels. + * The RT and BE priority classes both support up to 8 priority levels that + * can be specified using the lower 3-bits of the priority data. */ -#define IOPRIO_NR_LEVELS 8 -#define IOPRIO_BE_NR IOPRIO_NR_LEVELS +#define IOPRIO_LEVEL_NR_BITS 3 +#define IOPRIO_NR_LEVELS (1 << IOPRIO_LEVEL_NR_BITS) +#define IOPRIO_LEVEL_MASK (IOPRIO_NR_LEVELS - 1) +#define IOPRIO_PRIO_LEVEL(ioprio) ((ioprio) & IOPRIO_LEVEL_MASK) +#define IOPRIO_BE_NR IOPRIO_NR_LEVELS + +/* + * Possible values for the "which" argument of the ioprio_get() and + * ioprio_set() system calls (see "man ioprio_set"). + */ enum { IOPRIO_WHO_PROCESS = 1, IOPRIO_WHO_PGRP, @@ -44,7 +53,7 @@ enum { }; /* - * Fallback BE priority level. + * Fallback BE class priority level. */ #define IOPRIO_NORM 4 #define IOPRIO_BE_NORM IOPRIO_NORM From patchwork Thu Mar 9 21:54:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 661479 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0102FC74A44 for ; Thu, 9 Mar 2023 21:55:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231218AbjCIVzz (ORCPT ); Thu, 9 Mar 2023 16:55:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230151AbjCIVzi (ORCPT ); Thu, 9 Mar 2023 16:55:38 -0500 Received: from esa6.hgst.iphmx.com (esa6.hgst.iphmx.com [216.71.154.45]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C5682F0FEE; Thu, 9 Mar 2023 13:55:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1678398936; x=1709934936; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WwnlqWsoVBHzfPUYpLG/cmPs9ofwbigIiW2nxUFV5w8=; b=M8n/gwtJkkF1e2l5mqDlDd9ASuKraA4Iq+ju5cpohuQDJ0LhQzgWP5Jm 7kPORdR1CHPrMOW3uuegXAHgqKrmBGQaJMIXdHhYp9suIWEbrXLdghpbb tB6B1OkUo4wEuvYvEFPQPueKgNib7pLWg4N+x8qB/X5Qs9Y7T9cP5dhpT 3LVvNdj8vK4x/7PwLLw5hovWQoSylznPa/XGCVP8orWIGUPBKXT5oRK4H oZLQGVZE1Tc4bkzqqr2UohrTgl2g1ikHZTGh2yDOY2B/S/Jfnzm4+T/uB PvV+2sJmlIKyyYeTY1bOVAZ8hRFjRhTE4VI8PKAcSpTuEkdvWqc8Vn5DA A==; X-IronPort-AV: E=Sophos;i="5.98,247,1673884800"; d="scan'208";a="225270955" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 10 Mar 2023 05:55:36 +0800 IronPort-SDR: cqSfAEZJfAkGATXYUn2VtHTiI1n0cYB4gg3dgXYIogPmIYmgTWh5jhvIwGCZ71OB8EUFLkdnsx j/OrTXA4Mm3CUyNa6CzuvBTmysyCO5P+vrTIXIyxyH0d8G++4F4Ez8wSmckCJn+RhVSNd5DdSR lIztY0g4Moaxz+ov/sisNW3flS0zp32BWRP5AP6MV58rWr4hT+5Hgu0qtSof2jYRjurM3atN6B +DD9q+IuEZCD6xty6Cvcx+qg2UGjjJ9NnwMNdKCdi/L6oeCSzFvTfcQSmpL2Ji3Gn/+9o3SLH4 Re8= Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 09 Mar 2023 13:06:29 -0800 IronPort-SDR: K/OK8u+888tqI+XiFcIym9WhhKTU2RGrDGoveYjUDRlKfUv13vZmXLEwSYxVodW9Tw5R5lxiQf Z1uMjxnllZHFyuXVXRhGKD7KP0KIrPczhd4cfN9Vjc1Wkkf2WgkUbRwE/YGBM5NG2pK40SPJiK fIbWUM1+Y2gdRcWMm7JPyoMbpKh1lOvWXSasl9mdmF419hcHTB2Pngm6zqXzM2aNqpXVaiJ5DA aIOiDtdkEv8I84kH8Q4g35OJtxDamf89/5sJvvOHyM28hs5yUh078Iclfu5LofeplN/LSNiayZ qIk= WDCIronportException: Internal Received: from unknown (HELO x1-carbon.wdc.com) ([10.225.164.41]) by uls-op-cesaip01.wdc.com with ESMTP; 09 Mar 2023 13:55:35 -0800 From: Niklas Cassel To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Christoph Hellwig , Hannes Reinecke , Damien Le Moal , linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, linux-block@vger.kernel.org, Niklas Cassel Subject: [PATCH v4 04/19] scsi: core: allow libata to complete successful commands via EH Date: Thu, 9 Mar 2023 22:54:56 +0100 Message-Id: <20230309215516.3800571-5-niklas.cassel@wdc.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230309215516.3800571-1-niklas.cassel@wdc.com> References: <20230309215516.3800571-1-niklas.cassel@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org In SCSI, we get the sense data as part of the completion, for ATA however, we need to fetch the sense data as an extra step. For an aborted ATA command the sense data is fetched via libata's ->eh_strategy_handler(). For Command Duration Limits policy 0xD: The device shall complete the command without error with the additional sense code set to DATA CURRENTLY UNAVAILABLE. In order to handle this policy in libata, we intend to send a successful command via SCSI EH, and let libata's ->eh_strategy_handler() fetch the sense data for the good command. This is similar to how we handle an aborted ATA command, just that we need to read the Successful NCQ Commands log instead of the NCQ Command Error log. When we get a SATA completion with successful commands, ATA_SENSE will be set, indicating that some commands in the completion have sense data. The sense_valid bitmask in the Sense Data for Successful NCQ Commands log will inform exactly which commands that had sense data, which might be a subset of all the commands that was completed in the same completion. (Yet all will have ATA_SENSE set, since the status is per completion.) The successful commands that have e.g. a "DATA CURRENTLY UNAVAILABLE" sense data will have a SCSI ML byte set, so scsi_eh_flush_done_q() will not set the scmd->result to DID_TIME_OUT for these commands. However, the successful commands that did not have sense data, must not get their result marked as DID_TIME_OUT by SCSI EH. Add a new flag SCMD_FORCE_EH_SUCCESS, which tells SCSI EH to not mark a command as DID_TIME_OUT, even if it has scmd->result == SAM_STAT_GOOD. This will be used by libata in a follow-up patch. Signed-off-by: Niklas Cassel Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- drivers/scsi/scsi_error.c | 3 ++- include/scsi/scsi_cmnd.h | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2aa2c2aee6e7..cf5ec5f5f4f6 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -2165,7 +2165,8 @@ void scsi_eh_flush_done_q(struct list_head *done_q) * scsi_eh_get_sense), scmd->result is already * set, do not set DID_TIME_OUT. */ - if (!scmd->result) + if (!scmd->result && + !(scmd->flags & SCMD_FORCE_EH_SUCCESS)) scmd->result |= (DID_TIME_OUT << 16); SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index c2cb5f69635c..526def14e7fb 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -52,6 +52,11 @@ struct scsi_pointer { #define SCMD_TAGGED (1 << 0) #define SCMD_INITIALIZED (1 << 1) #define SCMD_LAST (1 << 2) +/* + * libata uses SCSI EH to fetch sense data for successful commands. + * SCSI EH should not overwrite scmd->result when SCMD_FORCE_EH_SUCCESS is set. + */ +#define SCMD_FORCE_EH_SUCCESS (1 << 3) #define SCMD_FAIL_IF_RECOVERING (1 << 4) /* flags preserved across unprep / reprep */ #define SCMD_PRESERVED_FLAGS (SCMD_INITIALIZED | SCMD_FAIL_IF_RECOVERING) From patchwork Thu Mar 9 21:54:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 661478 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A3700C6FD1C for ; Thu, 9 Mar 2023 21:56:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230074AbjCIV4L (ORCPT ); Thu, 9 Mar 2023 16:56:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50436 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230422AbjCIVzx (ORCPT ); Thu, 9 Mar 2023 16:55:53 -0500 Received: from esa6.hgst.iphmx.com (esa6.hgst.iphmx.com [216.71.154.45]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 200F3EFF56; Thu, 9 Mar 2023 13:55:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1678398940; x=1709934940; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=q4unhQS+exbmqBVmGkQor8xAT5EXcmccRGFkmsH65G4=; b=UG+B9R7nSTXhPBOVKJS2b/leqS4o2wu/aUreCP2OCLpYNtBU7tcMIMcZ bWoT5GXbpG3jyToEb/h0bncGwWbfJPO5uXdY7pSbFBVo9A8eHvB9vt0tM EmiYlSvNiEE4aSLq7wT0N9orRbM2fupB7r2WvPL6jZImpvp2ciHFGv2GL yM+3kLQR4m4DGfuEPrforDv4efBdCDtcI46a6Ymv28F8KBznaJjOO8K5F SitVdK0RnQNW36fCTRd6wpKxDWDPjzft/+ga40csp79uxVV8G7zU/MoTr for2LwjBNn9lZRpARrzIoDNu1+s+Y8h405v/y4n2Ib1pZhmFhxOnzdghh w==; X-IronPort-AV: E=Sophos;i="5.98,247,1673884800"; d="scan'208";a="225270961" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 10 Mar 2023 05:55:39 +0800 IronPort-SDR: pZ6dTxooT1b0yznLiBu3GypXme70zcnmdkCe4ZdJIi2AyLvOrVwuF+0S0xWyB7DZSZcIbDkfI/ RurFxfcg58Hjkx4Hvruob44qMhd0OKpvU3ttBAlJjEwJPe0h7FSANo3w/V/IEuOSuIZ7sccaDo FqLrQAUCznDRLnUIVGb8UNbF6F429lfvwgIPOF4ChM0DCkdiw0VO+FlbdFqoJYAea2LzPZzzAq P7UXpK+1UUqVSuvChr3QLkQMIQOct5//nSrnoe007wMi5XgWshRPI5sYiZwZJWF3VAB4HF+7mj BAQ= Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 09 Mar 2023 13:06:33 -0800 IronPort-SDR: tLpnnmDSXFd5JJt2g44ISlMQVK2Ci7YHs1yv0+4gvJankwXcwMrmvkWnNqb5wX/L9sXzXhKT2Q ib471drrs+dyNFDzu1m/E1P4nqi8TH2qkbzPF8tOegMJIT2MRYs2nW9QnzMuY1sKqsFAZbJ4LA +RXxZqlMvHeqk2tkIsdFa1hZBXO5ZWV/915nexhPla+U7JwEm+0wPNRnUbuq+SVfFiOR3Y0AfW tAhniIxMesnTzcj5k7J42pf20IbOxzSKdDlFcC5GAKHJYOOeTkWCj2MnALyVDql3YFQgczyhPI Yls= WDCIronportException: Internal Received: from unknown (HELO x1-carbon.wdc.com) ([10.225.164.41]) by uls-op-cesaip01.wdc.com with ESMTP; 09 Mar 2023 13:55:38 -0800 From: Niklas Cassel To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Christoph Hellwig , Hannes Reinecke , Damien Le Moal , linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, linux-block@vger.kernel.org, Niklas Cassel , Mike Christie , Bart Van Assche Subject: [PATCH v4 05/19] scsi: rename and move get_scsi_ml_byte() Date: Thu, 9 Mar 2023 22:54:57 +0100 Message-Id: <20230309215516.3800571-6-niklas.cassel@wdc.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230309215516.3800571-1-niklas.cassel@wdc.com> References: <20230309215516.3800571-1-niklas.cassel@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org SCSI has two different getters: - get_XXX_byte() (in scsi_cmnd.h) which takes a struct scsi_cmnd *, and - XXX_byte() (in scsi.h) which takes a scmd->result. The proper name for get_scsi_ml_byte() should thus be without the get_ prefix, as it takes a scmd->result. Rename the function to rectify this. (This change was suggested by Mike Christie.) Additionally, move get_scsi_ml_byte() to scsi_priv.h since both scsi_lib.c and scsi_error.c will need to use this helper in a follow-up patch. Cc: Mike Christie Signed-off-by: Niklas Cassel Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Reviewed-by: Bart Van Assche --- drivers/scsi/scsi_lib.c | 7 +------ drivers/scsi/scsi_priv.h | 5 +++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b7c569a42aa4..fac9c31161d2 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -578,11 +578,6 @@ static bool scsi_end_request(struct request *req, blk_status_t error, return false; } -static inline u8 get_scsi_ml_byte(int result) -{ - return (result >> 8) & 0xff; -} - /** * scsi_result_to_blk_status - translate a SCSI result code into blk_status_t * @result: scsi error code @@ -595,7 +590,7 @@ static blk_status_t scsi_result_to_blk_status(int result) * Check the scsi-ml byte first in case we converted a host or status * byte. */ - switch (get_scsi_ml_byte(result)) { + switch (scsi_ml_byte(result)) { case SCSIML_STAT_OK: break; case SCSIML_STAT_RESV_CONFLICT: diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 96284a0e13fe..74324fba4281 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -29,6 +29,11 @@ enum scsi_ml_status { SCSIML_STAT_TGT_FAILURE = 0x04, /* Permanent target failure */ }; +static inline u8 scsi_ml_byte(int result) +{ + return (result >> 8) & 0xff; +} + /* * Scsi Error Handler Flags */ From patchwork Thu Mar 9 21:55:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 661477 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2D805C6FD19 for ; Thu, 9 Mar 2023 21:56:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231264AbjCIV4m (ORCPT ); Thu, 9 Mar 2023 16:56:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50430 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231185AbjCIVzy (ORCPT ); Thu, 9 Mar 2023 16:55:54 -0500 Received: from esa6.hgst.iphmx.com (esa6.hgst.iphmx.com [216.71.154.45]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A8B2AF5A83; Thu, 9 Mar 2023 13:55:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1678398950; x=1709934950; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1i4sqNn+3mjUau8eq/zzmlqAHqw+oYQkGo3JDQZfROE=; b=JB+T8ckYpZdaRHF/igpZs8Y2sMuVEjkoub4w2944PnKR0pZ3Nqgt/X/3 OuOT2bcjskASkstLhKQ8lLtI9w3/E2BvDdtsa1k2mabqpxAWhb3d/Me2C S0U7vvONorhDKuctYrwvVK2ag5sj8tTICmjrLHr3HCoQyomniHmZEQBVc vk3ps2gF2UwhurdYU+VcuOe6oVsJ4j7Lbs0U7+5F0iCdzIg/G41knV6MO xl23f3Uz/2DP/JcVHELTxY36+ZErKGLkxhGIFwgRQBlg3cnZdwS1AFQUW p0CaIwbFrZhezF/aMSqjPDcLTYaXfdBSgK4evqf30NiGN1ikgYUNHRGQq w==; X-IronPort-AV: E=Sophos;i="5.98,247,1673884800"; d="scan'208";a="225271013" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 10 Mar 2023 05:55:50 +0800 IronPort-SDR: 0yVlf/yuIshtqFxTl3ARxVnZrzR94uQyRFCnXm9tOj26aoCbRrxdbmeHsVqHIznDez6hM7Goal 3DZTDhhL3mggcbBmE0MkDF+PTXIz1cEqCYEm5vwdcfoFdlYAx/+cXB5uO3rrfH0pIC4yx+H8Sb SXV1rrfIGqOXQrVaLN5Dg3yZJUb4sbCR9FuVp3+7aJk2YlJYgD+jgSgYP3y596iZqqQDeuom/m RwEtx/fr4nfpBUBABsbUzjuOHx8jP/p/A8YZy6lHGPDEkHSfau5xctFgzqCqnDXbWImepQZP6U Nsc= Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 09 Mar 2023 13:06:43 -0800 IronPort-SDR: tTiIOs8AcsVjZtIqbyJACIYchQBAcnxG99wRinwSbp9sZkRARbkpimgqOP+fRXGkkd1GfIqxaE 4gJF8GTXM+hfK8vE3VujQ80JRx5I6blSN27turae4RMx+BK+d/gVFpnIlHLR5XrbO4u0Fxbe/M 5IYchRm0KJ9C+TEoZeoONWOOeMr5qWbrzFkkDW+iO7EmuhORClPagyuoCfOnh3Z4EQkVhmY3BF EC7jNy+/dcBhTEbob0TpVkmOMymaGqKJJ/umayAeBsvwSZP69lnD/ToSOYAdaZHItt6F6uUj12 K10= WDCIronportException: Internal Received: from unknown (HELO x1-carbon.wdc.com) ([10.225.164.41]) by uls-op-cesaip01.wdc.com with ESMTP; 09 Mar 2023 13:55:48 -0800 From: Niklas Cassel To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Christoph Hellwig , Hannes Reinecke , Damien Le Moal , linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, linux-block@vger.kernel.org, Niklas Cassel Subject: [PATCH v4 08/19] scsi: detect support for command duration limits Date: Thu, 9 Mar 2023 22:55:00 +0100 Message-Id: <20230309215516.3800571-9-niklas.cassel@wdc.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230309215516.3800571-1-niklas.cassel@wdc.com> References: <20230309215516.3800571-1-niklas.cassel@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Damien Le Moal Introduce the function scsi_cdl_check() to detect if a device supports command duration limits (CDL). Support for the READ 16, WRITE 16, READ 32 and WRITE 32 commands are checked using the function scsi_report_opcode() to probe the rwcdlp and cdlp bits as they indicate the mode page defining the command duration limits descriptors that apply to the command being tested. If any of these commands support CDL, the field cdl_supported of struct scsi_device is set to 1 to indicate that the device supports CDL. Support for CDL for a device is advertizes through sysfs using the new cdl_supported device attribute. This attribute value is 1 for a device supporting CDL and 0 otherwise. Signed-off-by: Damien Le Moal Co-developed-by: Niklas Cassel Signed-off-by: Niklas Cassel --- Documentation/ABI/testing/sysfs-block-device | 9 +++ drivers/scsi/scsi.c | 81 ++++++++++++++++++++ drivers/scsi/scsi_scan.c | 3 + drivers/scsi/scsi_sysfs.c | 2 + include/scsi/scsi_device.h | 3 + 5 files changed, 98 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-block-device b/Documentation/ABI/testing/sysfs-block-device index 7ac7b19b2f72..ee3610a25845 100644 --- a/Documentation/ABI/testing/sysfs-block-device +++ b/Documentation/ABI/testing/sysfs-block-device @@ -95,3 +95,12 @@ Description: This file does not exist if the HBA driver does not implement support for the SATA NCQ priority feature, regardless of the device support for this feature. + + +What: /sys/block/*/device/cdl_supported +Date: Mar, 2023 +KernelVersion: v6.4 +Contact: linux-scsi@vger.kernel.org +Description: + (RO) Indicates if the device supports the command duration + limits feature found in some ATA and SCSI devices. diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 43ef70556027..e233eb6cce11 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -560,6 +560,87 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, } EXPORT_SYMBOL(scsi_report_opcode); +#define SCSI_CDL_CHECK_BUF_LEN 64 + +static bool scsi_cdl_check_cmd(struct scsi_device *sdev, u8 opcode, u16 sa, + unsigned char *buf) +{ + int ret; + u8 cdlp; + + /* Check operation code */ + ret = scsi_report_opcode(sdev, buf, SCSI_CDL_CHECK_BUF_LEN, opcode, sa); + if (ret <= 0) + return false; + + if ((buf[1] & 0x03) != 0x03) + return false; + + /* See SPC-6, one command format of REPORT SUPPORTED OPERATION CODES */ + cdlp = (buf[1] & 0x18) >> 3; + if (buf[0] & 0x01) { + /* rwcdlp == 1 */ + switch (cdlp) { + case 0x01: + /* T2A page */ + return true; + case 0x02: + /* T2B page */ + return true; + } + } else { + /* rwcdlp == 0 */ + switch (cdlp) { + case 0x01: + /* A page */ + return true; + case 0x02: + /* B page */ + return true; + } + } + + return false; +} + +/** + * scsi_cdl_check - Check if a SCSI device supports Command Duration Limits + * @sdev: The device to check + */ +void scsi_cdl_check(struct scsi_device *sdev) +{ + bool cdl_supported; + unsigned char *buf; + + buf = kmalloc(SCSI_CDL_CHECK_BUF_LEN, GFP_KERNEL); + if (!buf) { + sdev->cdl_supported = 0; + return; + } + + /* Check support for READ_16, WRITE_16, READ_32 and WRITE_32 commands */ + cdl_supported = + scsi_cdl_check_cmd(sdev, READ_16, 0, buf) || + scsi_cdl_check_cmd(sdev, WRITE_16, 0, buf) || + scsi_cdl_check_cmd(sdev, VARIABLE_LENGTH_CMD, READ_32, buf) || + scsi_cdl_check_cmd(sdev, VARIABLE_LENGTH_CMD, WRITE_32, buf); + if (cdl_supported) { + /* + * We have CDL support: force the use of READ16/WRITE16. + * READ32 and WRITE32 will be used for devices that support + * the T10_PI_TYPE2_PROTECTION protection type. + */ + sdev->use_16_for_rw = 1; + sdev->use_10_for_rw = 0; + + sdev->cdl_supported = 1; + } else { + sdev->cdl_supported = 0; + } + + kfree(buf); +} + /** * scsi_device_get - get an additional reference to a scsi_device * @sdev: device to get a reference to diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 4e842d79de31..0b703c136266 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1084,6 +1084,8 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, if (sdev->scsi_level >= SCSI_3) scsi_attach_vpd(sdev); + scsi_cdl_check(sdev); + sdev->max_queue_depth = sdev->queue_depth; WARN_ON_ONCE(sdev->max_queue_depth > sdev->budget_map.depth); sdev->sdev_bflags = *bflags; @@ -1621,6 +1623,7 @@ void scsi_rescan_device(struct device *dev) device_lock(dev); scsi_attach_vpd(sdev); + scsi_cdl_check(sdev); if (sdev->handler && sdev->handler->rescan) sdev->handler->rescan(sdev); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index ee28f73af4d4..4994148e685b 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -670,6 +670,7 @@ sdev_rd_attr (scsi_level, "%d\n"); sdev_rd_attr (vendor, "%.8s\n"); sdev_rd_attr (model, "%.16s\n"); sdev_rd_attr (rev, "%.4s\n"); +sdev_rd_attr (cdl_supported, "%d\n"); static ssize_t sdev_show_device_busy(struct device *dev, struct device_attribute *attr, @@ -1300,6 +1301,7 @@ static struct attribute *scsi_sdev_attrs[] = { &dev_attr_preferred_path.attr, #endif &dev_attr_queue_ramp_up_period.attr, + &dev_attr_cdl_supported.attr, REF_EVT(media_change), REF_EVT(inquiry_change_reported), REF_EVT(capacity_change_reported), diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 9564b47cf2ab..1cce42ad9f5c 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -216,6 +216,8 @@ struct scsi_device { unsigned ignore_media_change:1; /* Ignore MEDIA CHANGE on resume */ unsigned silence_suspend:1; /* Do not print runtime PM related messages */ + unsigned cdl_supported:1; /* Command duration limits supported */ + unsigned int queue_stopped; /* request queue is quiesced */ bool offline_already; /* Device offline message logged */ @@ -362,6 +364,7 @@ extern int scsi_register_device_handler(struct scsi_device_handler *scsi_dh); extern void scsi_remove_device(struct scsi_device *); extern int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh); void scsi_attach_vpd(struct scsi_device *sdev); +void scsi_cdl_check(struct scsi_device *sdev); extern struct scsi_device *scsi_device_from_queue(struct request_queue *q); extern int __must_check scsi_device_get(struct scsi_device *); From patchwork Thu Mar 9 21:55:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 661476 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9769FC74A4B for ; Thu, 9 Mar 2023 21:56:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231299AbjCIV4w (ORCPT ); Thu, 9 Mar 2023 16:56:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50432 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231195AbjCIVzz (ORCPT ); Thu, 9 Mar 2023 16:55:55 -0500 Received: from esa6.hgst.iphmx.com (esa6.hgst.iphmx.com [216.71.154.45]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C1762EE765; Thu, 9 Mar 2023 13:55:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1678398953; x=1709934953; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=h9g1jLGd6LxgCdMzZ9k85RB7pGJOXNOjT0fPf0VF2wc=; b=LI2yMZajO5LSlWlIo0KsAA8PTaqcKI+ouVuoRiFZ3ruCjXNJTh4EcC+I xPgydwTnZd3rPMYg81IdVajId4UmUTw98uEt1gAfDeKVCmYksyS4XuLII qP3mUCmyDUGyMtsARcGHFIqPvQa58D4+wgSjcAjSIvMMcyng//iTsE9wc PUq8CEW8on0qzpfFiIhaSXFjCo50JnnS43vMqXGB5dD66ON3mfawCFkkC V8u0ycUN5UY/6tB5T3Yc7DoT8IDCjyTtX6Q+y5LFf/vKl8LYAuwRNB6aO +KCMG/W513O0Hk3Da4R71LNUskMjNghjGQQk0DYuE4lE5qyW1kDGQpe5k A==; X-IronPort-AV: E=Sophos;i="5.98,247,1673884800"; d="scan'208";a="225271021" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 10 Mar 2023 05:55:53 +0800 IronPort-SDR: ctiV8lhgQExAV1Lys63D7Vz8/yFndEqRAbFzQ9RWo0l1f+jn09u/yJKXPLDPC6OzRrr3fd5Upv Pc0zXXJVh66LsfZXqsFWvNMRgkTtj7KMxjTT+gVINezw/thbky3N2S9mxVeH14XKCWvkc16JgJ vxcl+gDHyaVztAR0dl+alsQkv7IJ7J8C+PVD9VjFV59aFyZQUm/hIjI4JV49QsGZQryWtgyVmp 5WRl/SLkx5V+tOChJ4Aw5USeFwgYZsYy3VgPxK8KCZwiAKoP+Y7JhRYY1O5ujjSxO0zKVqO0RM GRA= Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 09 Mar 2023 13:06:46 -0800 IronPort-SDR: Jv4H9MqlpqtlCusoiUpHUJQnbq9wdkQUdIz+IuCPrwITDfvCMdoiTUkHZgRSBlrb9FHgHDJ3No htn6LhpgsOywmS4Yfm4yioLktc43bdcxICnxOYbx9KTXv0oa01uOrQ42IVXuXoWCKICzMX4T8S TyMA1lmsoFs0tYmT/cy/XIkc1JgwIkarTQt/Exl8sBMEiPxdyNKv3K7d7uD90Jq6cZBD8EVLpC jhMJcvfV2jPYyi7DoWYPkhxdSIXYBV+hkZOobSa5FaW2vfI7DGPC+Qsho8EJ9xCKw9Uhoocbkp vAk= WDCIronportException: Internal Received: from unknown (HELO x1-carbon.wdc.com) ([10.225.164.41]) by uls-op-cesaip01.wdc.com with ESMTP; 09 Mar 2023 13:55:52 -0800 From: Niklas Cassel To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Christoph Hellwig , Hannes Reinecke , Damien Le Moal , linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, linux-block@vger.kernel.org, Niklas Cassel Subject: [PATCH v4 09/19] scsi: allow enabling and disabling command duration limits Date: Thu, 9 Mar 2023 22:55:01 +0100 Message-Id: <20230309215516.3800571-10-niklas.cassel@wdc.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230309215516.3800571-1-niklas.cassel@wdc.com> References: <20230309215516.3800571-1-niklas.cassel@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Damien Le Moal Add the sysfs scsi device attribute cdl_enable to allow a user to turn enable or disable a device command duration limits feature. CDL is disabled by default. This feature must be explicitly enabled by a user by setting the cdl_enable attribute to 1. The new function scsi_cdl_enable() does not do anything beside setting the cdl_enable field of struct scsi_device in the case of a (real) scsi device (e.g. a SAS HDD). For ATA devices, the command duration limits feature needs to be enabled/disabled using the ATA feature sub-page of the control mode page. To do so, the scsi_cdl_enable() function checks if this mode page is supported using scsi_mode_sense(). If it is, scsi_mode_select() is used to enable and disable CDL. Signed-off-by: Damien Le Moal Co-developed-by: Niklas Cassel Signed-off-by: Niklas Cassel --- Documentation/ABI/testing/sysfs-block-device | 13 ++++ drivers/scsi/scsi.c | 62 ++++++++++++++++++++ drivers/scsi/scsi_sysfs.c | 31 ++++++++++ include/scsi/scsi_device.h | 2 + 4 files changed, 108 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-block-device b/Documentation/ABI/testing/sysfs-block-device index ee3610a25845..626d48ac504b 100644 --- a/Documentation/ABI/testing/sysfs-block-device +++ b/Documentation/ABI/testing/sysfs-block-device @@ -104,3 +104,16 @@ Contact: linux-scsi@vger.kernel.org Description: (RO) Indicates if the device supports the command duration limits feature found in some ATA and SCSI devices. + + +What: /sys/block/*/device/cdl_enable +Date: Mar, 2023 +KernelVersion: v6.4 +Contact: linux-scsi@vger.kernel.org +Description: + (RW) For a device supporting the command duration limits + feature, write to the file to turn on or off the feature. + By default this feature is turned off. + Writing "1" to this file enables the use of command duration + limits for read and write commands in the kernel and turns on + the feature on the device. Writing "0" disables the feature. diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index e233eb6cce11..385a09a387b2 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -641,6 +641,68 @@ void scsi_cdl_check(struct scsi_device *sdev) kfree(buf); } +/** + * scsi_cdl_enable - Enable or disable a SCSI device supports for Command + * Duration Limits + * @sdev: The target device + * @enable: the target state + */ +int scsi_cdl_enable(struct scsi_device *sdev, bool enable) +{ + struct scsi_mode_data data; + struct scsi_sense_hdr sshdr; + struct scsi_vpd *vpd; + bool is_ata = false; + char buf[64]; + int ret; + + if (!sdev->cdl_supported) + return -EOPNOTSUPP; + + rcu_read_lock(); + vpd = rcu_dereference(sdev->vpd_pg89); + if (vpd) + is_ata = true; + rcu_read_unlock(); + + /* + * For ATA devices, CDL needs to be enabled with a SET FEATURES command. + */ + if (is_ata) { + char *buf_data; + int len; + + ret = scsi_mode_sense(sdev, 0x08, 0x0a, 0xf2, buf, sizeof(buf), + 5 * HZ, 3, &data, NULL); + if (ret) + return -EINVAL; + + /* Enable CDL using the ATA feature page */ + len = min_t(size_t, sizeof(buf), + data.length - data.header_length - + data.block_descriptor_length); + buf_data = buf + data.header_length + + data.block_descriptor_length; + if (enable) + buf_data[4] = 0x02; + else + buf_data[4] = 0; + + ret = scsi_mode_select(sdev, 1, 0, buf_data, len, 5 * HZ, 3, + &data, &sshdr); + if (ret) { + if (scsi_sense_valid(&sshdr)) + scsi_print_sense_hdr(sdev, + dev_name(&sdev->sdev_gendev), &sshdr); + return ret; + } + } + + sdev->cdl_enable = enable; + + return 0; +} + /** * scsi_device_get - get an additional reference to a scsi_device * @sdev: device to get a reference to diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 4994148e685b..9a54b2c0fee7 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1222,6 +1222,36 @@ static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR, sdev_show_queue_ramp_up_period, sdev_store_queue_ramp_up_period); +static ssize_t sdev_show_cdl_enable(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + + return sysfs_emit(buf, "%d\n", (int)sdev->cdl_enable); +} + +static ssize_t sdev_store_cdl_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + bool v; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (kstrtobool(buf, &v)) + return -EINVAL; + + ret = scsi_cdl_enable(to_scsi_device(dev), v); + if (ret) + return ret; + + return count; +} +static DEVICE_ATTR(cdl_enable, S_IRUGO | S_IWUSR, + sdev_show_cdl_enable, sdev_store_cdl_enable); + static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj, struct attribute *attr, int i) { @@ -1302,6 +1332,7 @@ static struct attribute *scsi_sdev_attrs[] = { #endif &dev_attr_queue_ramp_up_period.attr, &dev_attr_cdl_supported.attr, + &dev_attr_cdl_enable.attr, REF_EVT(media_change), REF_EVT(inquiry_change_reported), REF_EVT(capacity_change_reported), diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 1cce42ad9f5c..970467d451bf 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -217,6 +217,7 @@ struct scsi_device { unsigned silence_suspend:1; /* Do not print runtime PM related messages */ unsigned cdl_supported:1; /* Command duration limits supported */ + unsigned cdl_enable:1; /* Enable/disable Command duration limits */ unsigned int queue_stopped; /* request queue is quiesced */ bool offline_already; /* Device offline message logged */ @@ -365,6 +366,7 @@ extern void scsi_remove_device(struct scsi_device *); extern int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh); void scsi_attach_vpd(struct scsi_device *sdev); void scsi_cdl_check(struct scsi_device *sdev); +int scsi_cdl_enable(struct scsi_device *sdev, bool enable); extern struct scsi_device *scsi_device_from_queue(struct request_queue *q); extern int __must_check scsi_device_get(struct scsi_device *); From patchwork Thu Mar 9 21:55:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 661475 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05769C61DA4 for ; Thu, 9 Mar 2023 21:57:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230416AbjCIV5N (ORCPT ); Thu, 9 Mar 2023 16:57:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50992 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231232AbjCIV4K (ORCPT ); Thu, 9 Mar 2023 16:56:10 -0500 Received: from esa6.hgst.iphmx.com (esa6.hgst.iphmx.com [216.71.154.45]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DA90AF4D96; Thu, 9 Mar 2023 13:55:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1678398959; x=1709934959; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=mmP5xhNzgcv2fg9WGa4um6nD+0nuRWAD43QMcPgLImE=; b=dETs0L99wD7yxb7s/3m5Uh6qPhQx5lxADDrtBNqmSSc1vYlto27vmvpn bU85W0GtlpjcM0At4OviPmwfA8ugFMNm2waU/VT2XI27+eay0JXSrxC2Y 1iexaK5kdZo3hoYAKW0P23lmhRxoNhfHEOA78TMaiv+fQGMbe5B8bg7QT SVgoiP8aTIK6T7DYkhq9cz/N0XNsqQlPJjt5k3S/I7UnADrec0m9TWkWR 6TUZE4ZW70SAUqB8dj75iriroO5Ok/GcGEcn7QVSERtl1v3aBpEBC+KUR aXJaPRO1JkB+2UFBFLjry+bepwngwayPMgBBll5agU6jZ5ozWOD+MeDSA Q==; X-IronPort-AV: E=Sophos;i="5.98,247,1673884800"; d="scan'208";a="225271030" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 10 Mar 2023 05:55:59 +0800 IronPort-SDR: OH7ARXoip+2Ozlq7+0cIqu7YlL5Cd82BPa18KG81NUDBxwtBmI0mjM5aizTcLO4wuTn/uMmO+K guY7QLn6hWkt8ajBwBzJcLGQ8Rc1a2kgcgsl0uv9Ka7KNwDcFvTw7g0iCuu6WeAEkKosUDZDSi klJRHgyL/8lacAM2EFAutP8LMYGmK0iTwKTeg+5c4JpyvcYYPa0cvRXhs2LCmeLFGkq8O9HB4/ Ll9K+NvkvV4DYm9/LX1yhSF1tOKWIKcgX8qpMbIE0bSda0/RXqc/cz2Q7Z1OKlG/6onVA840cs ezA= Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 09 Mar 2023 13:06:53 -0800 IronPort-SDR: fgyAYIZClVEdcBaXQ2JtP9R8LrxgXHODlgB3SsiJgClfnXwOmuNakKad3BzwzziBnt7t59muYq 899srIBNJAI83UrhtIE3XaGSDbB8+gHkSzN74GZT7hJFkQMCEpjMM/q3NEXiQCs/NwU7rvi8Yt lEb5PEK4ZQ9rqw5/Rut1iQI5vvTJvnbrjhpHxTzUk2p+cqfrr85U/2BEV6Hu1+fVShqj4kHlgP 8S2uw1A5/sVxzXMtMOPDASJPVp1UkVvZYqq8bRj5jkz3s2Q9Ei6ynbciDZtecr1YFTe96jeGAS ZSk= WDCIronportException: Internal Received: from unknown (HELO x1-carbon.wdc.com) ([10.225.164.41]) by uls-op-cesaip01.wdc.com with ESMTP; 09 Mar 2023 13:55:58 -0800 From: Niklas Cassel To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Christoph Hellwig , Hannes Reinecke , Damien Le Moal , linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, linux-block@vger.kernel.org, Niklas Cassel Subject: [PATCH v4 11/19] scsi: sd: handle read/write CDL timeout failures Date: Thu, 9 Mar 2023 22:55:03 +0100 Message-Id: <20230309215516.3800571-12-niklas.cassel@wdc.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230309215516.3800571-1-niklas.cassel@wdc.com> References: <20230309215516.3800571-1-niklas.cassel@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Commands using a duration limit descriptor that has limit policies set to a value other than 0x0 may be failed by the device if one of the limits are exceeded. For such commands, since the failure is the result of the user duration limit configuration and workload, the commands should not be retried and terminated immediately. Furthermore, to allow the user to differentiate these "soft" failures from hard errors due to hardware problem, a different error code than EIO should be returned. There are 2 cases to consider: (1) The failure is due to a limit policy failing the command with a check condition sense key, that is, any limit policy other than 0xD. For this case, scsi_check_sense() is modified to detect failures with the ABORTED COMMAND sense key and the COMMAND TIMEOUT BEFORE PROCESSING or COMMAND TIMEOUT DURING PROCESSING or COMMAND TIMEOUT DURING PROCESSING DUE TO ERROR RECOVERY additional sense code. For these failures, a SUCCESS disposition is returned so that scsi_finish_command() is called to terminate the command. (2) The failure is due to a limit policy set to 0xD, which result in the command being terminated with a GOOD status, COMPLETED sense key, and DATA CURRENTLY UNAVAILABLE additional sense code. To handle this case, the scsi_check_sense() is modified to return a SUCCESS disposition so that scsi_finish_command() is called to terminate the command. In addition, scsi_decide_disposition() has to be modified to see if a command being terminated with GOOD status has sense data. This is as defined in SCSI Primary Commands - 6 (SPC-6), so all according to spec, even if GOOD status commands were not checked before. If scsi_check_sense() detects sense data representing a duration limit, scsi_check_sense() will set the newly introduced SCSI ML byte SCSIML_STAT_DL_TIMEOUT. This SCSI ML byte is checked in scsi_noretry_cmd(), so that a command that failed because of a CDL timeout cannot be retried. The SCSI ML byte is also checked in scsi_result_to_blk_status() to complete the command request with the BLK_STS_DURATION_LIMIT status, which result in the user seeing ETIME errors for the failed commands. Co-developed-by: Damien Le Moal Signed-off-by: Damien Le Moal Signed-off-by: Niklas Cassel --- drivers/scsi/scsi_error.c | 45 +++++++++++++++++++++++++++++++++++++++ drivers/scsi/scsi_lib.c | 4 ++++ drivers/scsi/scsi_priv.h | 1 + 3 files changed, 50 insertions(+) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index cf5ec5f5f4f6..dc85a75b33d9 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -536,6 +536,7 @@ static inline void set_scsi_ml_byte(struct scsi_cmnd *cmd, u8 status) */ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd) { + struct request *req = scsi_cmd_to_rq(scmd); struct scsi_device *sdev = scmd->device; struct scsi_sense_hdr sshdr; @@ -595,6 +596,22 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd) if (sshdr.asc == 0x10) /* DIF */ return SUCCESS; + /* + * Check aborts due to command duration limit policy: + * ABORTED COMMAND additional sense code with the + * COMMAND TIMEOUT BEFORE PROCESSING or + * COMMAND TIMEOUT DURING PROCESSING or + * COMMAND TIMEOUT DURING PROCESSING DUE TO ERROR RECOVERY + * additional sense code qualifiers. + */ + if (sshdr.asc == 0x2e && + sshdr.ascq >= 0x01 && sshdr.ascq <= 0x03) { + set_scsi_ml_byte(scmd, SCSIML_STAT_DL_TIMEOUT); + req->cmd_flags |= REQ_FAILFAST_DEV; + req->rq_flags |= RQF_QUIET; + return SUCCESS; + } + if (sshdr.asc == 0x44 && sdev->sdev_bflags & BLIST_RETRY_ITF) return ADD_TO_MLQUEUE; if (sshdr.asc == 0xc1 && sshdr.ascq == 0x01 && @@ -691,6 +708,14 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd) } return SUCCESS; + case COMPLETED: + if (sshdr.asc == 0x55 && sshdr.ascq == 0x0a) { + set_scsi_ml_byte(scmd, SCSIML_STAT_DL_TIMEOUT); + req->cmd_flags |= REQ_FAILFAST_DEV; + req->rq_flags |= RQF_QUIET; + } + return SUCCESS; + default: return SUCCESS; } @@ -785,6 +810,14 @@ static enum scsi_disposition scsi_eh_completed_normally(struct scsi_cmnd *scmd) switch (get_status_byte(scmd)) { case SAM_STAT_GOOD: scsi_handle_queue_ramp_up(scmd->device); + if (scmd->sense_buffer && SCSI_SENSE_VALID(scmd)) + /* + * If we have sense data, call scsi_check_sense() in + * order to set the correct SCSI ML byte (if any). + * No point in checking the return value, since the + * command has already completed successfully. + */ + scsi_check_sense(scmd); fallthrough; case SAM_STAT_COMMAND_TERMINATED: return SUCCESS; @@ -1807,6 +1840,10 @@ bool scsi_noretry_cmd(struct scsi_cmnd *scmd) return !!(req->cmd_flags & REQ_FAILFAST_DRIVER); } + /* Never retry commands aborted due to a duration limit timeout */ + if (scsi_ml_byte(scmd->result) == SCSIML_STAT_DL_TIMEOUT) + return true; + if (!scsi_status_is_check_condition(scmd->result)) return false; @@ -1966,6 +2003,14 @@ enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *scmd) if (scmd->cmnd[0] == REPORT_LUNS) scmd->device->sdev_target->expecting_lun_change = 0; scsi_handle_queue_ramp_up(scmd->device); + if (scmd->sense_buffer && SCSI_SENSE_VALID(scmd)) + /* + * If we have sense data, call scsi_check_sense() in + * order to set the correct SCSI ML byte (if any). + * No point in checking the return value, since the + * command has already completed successfully. + */ + scsi_check_sense(scmd); fallthrough; case SAM_STAT_COMMAND_TERMINATED: return SUCCESS; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 633c4e8af830..b894432ca0b9 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -601,6 +601,8 @@ static blk_status_t scsi_result_to_blk_status(int result) return BLK_STS_MEDIUM; case SCSIML_STAT_TGT_FAILURE: return BLK_STS_TARGET; + case SCSIML_STAT_DL_TIMEOUT: + return BLK_STS_DURATION_LIMIT; } switch (host_byte(result)) { @@ -798,6 +800,8 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result) blk_stat = BLK_STS_ZONE_OPEN_RESOURCE; } break; + case COMPLETED: + fallthrough; default: action = ACTION_FAIL; break; diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 74324fba4281..f42388ecb024 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -27,6 +27,7 @@ enum scsi_ml_status { SCSIML_STAT_NOSPC = 0x02, /* Space allocation on the dev failed */ SCSIML_STAT_MED_ERROR = 0x03, /* Medium error */ SCSIML_STAT_TGT_FAILURE = 0x04, /* Permanent target failure */ + SCSIML_STAT_DL_TIMEOUT = 0x05, /* Command Duration Limit timeout */ }; static inline u8 scsi_ml_byte(int result) From patchwork Thu Mar 9 21:55:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 661474 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3B78DC6FD19 for ; Thu, 9 Mar 2023 21:57:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231284AbjCIV5z (ORCPT ); Thu, 9 Mar 2023 16:57:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51650 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231270AbjCIV4o (ORCPT ); Thu, 9 Mar 2023 16:56:44 -0500 Received: from esa6.hgst.iphmx.com (esa6.hgst.iphmx.com [216.71.154.45]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 262A9F6386; Thu, 9 Mar 2023 13:56:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1678398965; x=1709934965; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=U56GFe28NZXQ6UkI4778Mu/NlPLVOeSg97GcX8sR+Hw=; b=Xl81mVwZnNt1gzYRnO+K8B9A2QW94V6M0Mz6eK0N9eezJiKYc9xfkUS4 /rAqza7gP1qMpNJuAa9YmTR6f/9PLCB9NhXxN47ei43mVwtf+XWYeTqIg OGJnJkKje84StLUgLRqYc1DY9r2H+KCRi/6wrYMQtXaQPS6KOFesx00YV 70uzkLNmvTkK0L3bGXrLjLSj2ndkGdibCdI9z66IyVDy5jymVgTflVeqp QLdmrCUdrfsvqjihS3HLOTAVullYvElB6SuYDWGk7eV5kojqR+ONuybFU i6Wt3v3I208HAc+jBjsRsIxFfBz9sn4MeG1erfkSEkPThK4pqGGco+tvy g==; X-IronPort-AV: E=Sophos;i="5.98,247,1673884800"; d="scan'208";a="225271035" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 10 Mar 2023 05:56:04 +0800 IronPort-SDR: 0H82iQ4Z4d8M8XdXREcI7Kg4fj3UEaCTqiEvfEufUpcZtr+fb8cACTJ0PqZ3ScNMcPWMIa4OhZ s0OkzQxyI8tGemnCmj807/DFBJqg1QPmqulPVTgECLpv+z764ZWslQJi67q262UpcIb6rZOH5e esYreoCs83fkCZEscxx5itjSYpzO/MwvGaa/uKV4Le7jvh777Pe9pbi3H4//6Kqxe+Rf3VHtI3 ZCm8g2D/gqHr0KEmAFflszSVL1UDaqhi9Mhivxt9Srr1keWP7RLbsYmsQ/71Wl0vvyOg/l/NZ/ N4E= Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 09 Mar 2023 13:06:58 -0800 IronPort-SDR: 9tD9TIweKFMYAPLajH/piobJjD90VI+NrIMjj2kW5/qCxTmMlBNTWSPxEVFeXJiU3dLqjqr1Pl maUf/moKRiUqzuFd4taDfyOg9poGj1biZrXqBKcWEbuJYZfTgSJnWJ7sOnLimJD0gUUS7njJBZ K8c8w0YIIBlh5n1L4e4QNE69DuVb8JzUaqRhMiImySm61zypsz6fA9oUMhW5YtJ3OAaGqcYdp8 zKk+TrSjz/Yg59v5Fpxq0omKaJx/NyGy4lYPvrAvOif0ogRJWHA9e9LtIboAuUP/4Mp+/k5LeX pHo= WDCIronportException: Internal Received: from unknown (HELO x1-carbon.wdc.com) ([10.225.164.41]) by uls-op-cesaip01.wdc.com with ESMTP; 09 Mar 2023 13:56:03 -0800 From: Niklas Cassel To: Damien Le Moal Cc: Christoph Hellwig , Hannes Reinecke , linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, linux-block@vger.kernel.org, Niklas Cassel Subject: [PATCH v4 13/19] ata: libata: change ata_eh_request_sense() to not set CHECK_CONDITION Date: Thu, 9 Mar 2023 22:55:05 +0100 Message-Id: <20230309215516.3800571-14-niklas.cassel@wdc.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230309215516.3800571-1-niklas.cassel@wdc.com> References: <20230309215516.3800571-1-niklas.cassel@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Currently, ata_eh_request_sense() unconditionally sets the scsicmd->result to SAM_STAT_CHECK_CONDITION. For Command Duration Limits policy 0xD: The device shall complete the command without error (SAM_STAT_GOOD) with the additional sense code set to DATA CURRENTLY UNAVAILABLE. It is perfectly fine to have sense data for a command that returned completion without error. In order to support for CDL policy 0xD, we have to remove this assumption that having sense data means that the command failed (SAM_STAT_CHECK_CONDITION). Change ata_eh_request_sense() to not set SAM_STAT_CHECK_CONDITION, and instead move the setting of SAM_STAT_CHECK_CONDITION to the single caller that wants SAM_STAT_CHECK_CONDITION set, that way ata_eh_request_sense() can be reused in a follow-up patch that adds support for CDL policy 0xD. The only caller of ata_eh_request_sense() is protected by: if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)), so we can remove this duplicated check from ata_eh_request_sense() itself. Additionally, ata_eh_request_sense() is only called from ata_eh_analyze_tf(), which is only called when iteratating the QCs using ata_qc_for_each_raw(), which does not include the internal tag, so cmd can never be NULL (all non-internal commands have qc->scsicmd set), so remove the !cmd check as well. Signed-off-by: Niklas Cassel Reviewed-by: Hannes Reinecke --- drivers/ata/libata-eh.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index a6c901811802..598ae07195b6 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1401,8 +1401,11 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key) * * LOCKING: * Kernel thread context (may sleep). + * + * RETURNS: + * true if sense data could be fetched, false otherwise. */ -static void ata_eh_request_sense(struct ata_queued_cmd *qc) +static bool ata_eh_request_sense(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; struct ata_device *dev = qc->dev; @@ -1411,15 +1414,12 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc) if (ata_port_is_frozen(qc->ap)) { ata_dev_warn(dev, "sense data available but port frozen\n"); - return; + return false; } - if (!cmd || qc->flags & ATA_QCFLAG_SENSE_VALID) - return; - if (!ata_id_sense_reporting_enabled(dev->id)) { ata_dev_warn(qc->dev, "sense data reporting disabled\n"); - return; + return false; } ata_tf_init(dev, &tf); @@ -1432,13 +1432,19 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc) /* Ignore err_mask; ATA_ERR might be set */ if (tf.status & ATA_SENSE) { if (ata_scsi_sense_is_valid(tf.lbah, tf.lbam, tf.lbal)) { - ata_scsi_set_sense(dev, cmd, tf.lbah, tf.lbam, tf.lbal); + /* Set sense without also setting scsicmd->result */ + scsi_build_sense_buffer(dev->flags & ATA_DFLAG_D_SENSE, + cmd->sense_buffer, tf.lbah, + tf.lbam, tf.lbal); qc->flags |= ATA_QCFLAG_SENSE_VALID; + return true; } } else { ata_dev_warn(dev, "request sense failed stat %02x emask %x\n", tf.status, err_mask); } + + return false; } /** @@ -1588,8 +1594,9 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc) * was not included in the NCQ command error log * (i.e. NCQ autosense is not supported by the device). */ - if (!(qc->flags & ATA_QCFLAG_SENSE_VALID) && (stat & ATA_SENSE)) - ata_eh_request_sense(qc); + if (!(qc->flags & ATA_QCFLAG_SENSE_VALID) && + (stat & ATA_SENSE) && ata_eh_request_sense(qc)) + set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION); if (err & ATA_ICRC) qc->err_mask |= AC_ERR_ATA_BUS; if (err & (ATA_UNC | ATA_AMNF)) From patchwork Thu Mar 9 21:55:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 661473 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C3A04C74A5B for ; Thu, 9 Mar 2023 21:58:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230422AbjCIV6O (ORCPT ); Thu, 9 Mar 2023 16:58:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51310 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230143AbjCIV5e (ORCPT ); Thu, 9 Mar 2023 16:57:34 -0500 Received: from esa6.hgst.iphmx.com (esa6.hgst.iphmx.com [216.71.154.45]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AD301F603A; Thu, 9 Mar 2023 13:56:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1678398970; x=1709934970; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1JaAwgGHLI4jFdeVVjtrT7wVpPnCMuROX+o5Q7kJxUg=; b=HlrPeUxPynR0yBXApa3zLNxfJ3NI+3bxATc1ue0/nF4B9IXIB7aRGt3A MkQJ+cBut3wg2YkUEm8PpJJvybpBe60tCxryf+9u5OWG/qm4lF8OkUTLj zYyFjpw1fWW6B0Q4PLz/ZkkrP/RmyHPhwlPhkN+SykisTkQAOtiR7XmDd rUk/QcVCIXfvEZf1C5vIlyKEgLZJDnIOpguA2kQ61DjndlQA3GfzfmStQ gxlEHWHEBcKJU+I+dSf6ppxTepSUEyDsDJxIgZRSDAsUrKhdp7MAPZF/U Ae+Ry2hZmwACWA63ZFwIsM7Rg4wvqCH5hjndWjuni4rDYoz7ySEc05I69 Q==; X-IronPort-AV: E=Sophos;i="5.98,247,1673884800"; d="scan'208";a="225271044" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 10 Mar 2023 05:56:10 +0800 IronPort-SDR: 2TV7/rJzXf/l7wckOIZs1ayX2kEm7UxMtt9r0TsXHzkUpsdSFGFs1oVyqqlFFCg3GV+qxWB8UX YgIxsU8rAOgvZ7hmoO5vYuuf1wz1N1BhRUDDMyIVHDyGwwmPjs4GBOXPpu+XYgxmIQms947ZE3 S9ZMacnsvZE7KZ6Y2g34fJYEJ3kMnByS/G1ItPC57NGfkp9iDuhbBBmRgUOkklezQPkJR3LR3T rzXwMp3Piusm24qXjsL/IXfEU4m/104pRrGDMxe1skTYAQ7j2Dr720LT2nQEL9JhrhsyBYifVs SJ0= Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 09 Mar 2023 13:07:03 -0800 IronPort-SDR: 2oDoqb8Ww4HORQAlCzd3l/1Bl2x4R2YCHQ1LK6zyHCM/uYkXfvcu27epRViPJNuUdJ7zWPzUiU +zMkagppYgqJqhP0dDzb8ZSD47UcVbENrMeECrMTFc0a3+IdGH7UuN1hKDA31ERKS/mbBLk81c HFwnIy1pnhQGLILS7aJ03RGF/T6kMXS7gHqtFwVpb+D0rmqFqra1vF6b+T4c9jWB4sN2vOnfOv kGCqN4ii82LnRXIQFtWVh0rKQkG6pgUb1IimvywBhfS+pdWeNIP9gUgNSqnH5rXJNoPBlpNYMf C2Q= WDCIronportException: Internal Received: from unknown (HELO x1-carbon.wdc.com) ([10.225.164.41]) by uls-op-cesaip01.wdc.com with ESMTP; 09 Mar 2023 13:56:09 -0800 From: Niklas Cassel To: Damien Le Moal Cc: Christoph Hellwig , Hannes Reinecke , linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, linux-block@vger.kernel.org, Niklas Cassel Subject: [PATCH v4 15/19] ata: libata-scsi: handle CDL bits in ata_scsiop_maint_in() Date: Thu, 9 Mar 2023 22:55:07 +0100 Message-Id: <20230309215516.3800571-16-niklas.cassel@wdc.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230309215516.3800571-1-niklas.cassel@wdc.com> References: <20230309215516.3800571-1-niklas.cassel@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Damien Le Moal For a scsi MAINTENANCE_IN/MI_REPORT_SUPPORTED_OPERATION_CODES operation, add the translation of the rwcdlp and cdlp bits for the READ16 and WRITE16 commands. If the ATA device does not support command duration limits, these bits are always 0. If the ATA device supports command duration limits, the rwcdlp bit is set to 1 for READ16 and WRITE16 and the cdlp bits are set to 0x1 for READ16 and 0x2 for WRITE16. These correspond to the T2A mode page containing the read descriptors and to the T2B mode page containing the write descriptors, as defined in SAT-5. Signed-off-by: Damien Le Moal Signed-off-by: Niklas Cassel Reviewed-by: Hannes Reinecke --- drivers/ata/libata-scsi.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 716c33af999c..2a0a04c9e658 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3235,7 +3235,7 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) { struct ata_device *dev = args->dev; u8 *cdb = args->cmd->cmnd; - u8 supported = 0; + u8 supported = 0, cdlp = 0, rwcdlp = 0; unsigned int err = 0; if (cdb[2] != 1 && cdb[2] != 3) { @@ -3262,10 +3262,8 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) case MAINTENANCE_IN: case READ_6: case READ_10: - case READ_16: case WRITE_6: case WRITE_10: - case WRITE_16: case ATA_12: case ATA_16: case VERIFY: @@ -3275,6 +3273,28 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) case START_STOP: supported = 3; break; + case READ_16: + supported = 3; + if (dev->flags & ATA_DFLAG_CDL) { + /* + * CDL read descriptors map to the T2A page, that is, + * rwcdlp = 0x01 and cdlp = 0x01 + */ + rwcdlp = 0x01; + cdlp = 0x01 << 3; + } + break; + case WRITE_16: + supported = 3; + if (dev->flags & ATA_DFLAG_CDL) { + /* + * CDL write descriptors map to the T2B page, that is, + * rwcdlp = 0x01 and cdlp = 0x02 + */ + rwcdlp = 0x01; + cdlp = 0x02 << 3; + } + break; case ZBC_IN: case ZBC_OUT: if (ata_id_zoned_cap(dev->id) || @@ -3290,7 +3310,9 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) break; } out: - rbuf[1] = supported; /* supported */ + /* One command format */ + rbuf[0] = rwcdlp; + rbuf[1] = cdlp | supported; return err; } From patchwork Thu Mar 9 21:55:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 661472 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0B354C74A5B for ; Thu, 9 Mar 2023 21:58:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231395AbjCIV6p (ORCPT ); Thu, 9 Mar 2023 16:58:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52810 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231392AbjCIV5x (ORCPT ); Thu, 9 Mar 2023 16:57:53 -0500 Received: from esa6.hgst.iphmx.com (esa6.hgst.iphmx.com [216.71.154.45]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 96028105542; Thu, 9 Mar 2023 13:56:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1678398984; x=1709934984; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=oat3fRaUHGz/GDaU521bbBVFkXEgU1y1LbC4eDih07o=; b=Vpo9hmt22bjA1lzGvPGCXTFoLwlooBU9EfiQurDke6oI/x0GIdCdcql+ r2aerFyBO+YrY7F/fu2AaS9z1NjlJZYQV1ajbFMUv8UnMkKtTFBRqWkz2 jStv1qrhlZa1f+lxG0HIqloBP3MGyGf9nVPoIlmA7eycGg03Cx56RaA1h 1LiRjBmqzgwYCMqoFt9ij5vzCbTWQmIpmhtJgm79B5P+dsS7vwPCM/SbT U0epzxDBBmGT8LqvP5kxzqCM2G66kxs5qnpAS/1qfAAW08ygkO3wsvnvN SI7PdIYz6JNDTkDHSg9deZ+2YFdwtvHGhly0en8TNKgA7o7xdHjuZleQV Q==; X-IronPort-AV: E=Sophos;i="5.98,247,1673884800"; d="scan'208";a="225271066" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 10 Mar 2023 05:56:19 +0800 IronPort-SDR: xRXFMMLSqNIhYqezIbWncWj6V/39E5eOyUfw+14S206nAEqRUac+XnyLaeDr+H6MwGmEbBnT1j tUbGBlvy2rWrDyTWn0PJplNp7QBJrQJd7bj4SVd0sZQ02aeEzVKjUEB7YZI0QmRJ0doqKEJbP8 nz4fvsGlvIaxWYgQxxqqQdlGGlUo9sQPiqhO7owOthGhgd4LsopgPIKu09+z3HIhCtXM2NyVmu nvlolpEiK+h7+LJR6UCF+lVTE56jnUNWUUt6YxEAWXFwds5orQ3WnVy7mZYaP9DZDX8GyB9ugd 3W0= Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 09 Mar 2023 13:07:12 -0800 IronPort-SDR: yGXsDYQtdN2mk7hw6PghvhNDWf+EXCgevAOV1nximzDxVVL/eTD35dXqFWv0gLrhH5Ebwby/SN IfR4CKnqlmp4yQa+9lHxX/Shi1PxhEsohP4Imrghoe8UW+jhGv1DtLPYmzhTudxSNyHHGX/NBw mXDB9RRFt3zxAhyqw4O8h4aPQqVDimfZ23oL+qkmhRFYO4Uerghf3lBAvvt6xUabU7wvYOREZR XmxodZU2QMh9RrGLfDtSlKAn0p2yr0JUksmlUaTP/rDSudCYTlVUFGuR1/FbQ/pE278h2o1bXM o7w= WDCIronportException: Internal Received: from unknown (HELO x1-carbon.wdc.com) ([10.225.164.41]) by uls-op-cesaip01.wdc.com with ESMTP; 09 Mar 2023 13:56:18 -0800 From: Niklas Cassel To: Damien Le Moal Cc: Christoph Hellwig , Hannes Reinecke , linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, linux-block@vger.kernel.org, Niklas Cassel Subject: [PATCH v4 18/19] ata: libata: set read/write commands CDL index Date: Thu, 9 Mar 2023 22:55:10 +0100 Message-Id: <20230309215516.3800571-19-niklas.cassel@wdc.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230309215516.3800571-1-niklas.cassel@wdc.com> References: <20230309215516.3800571-1-niklas.cassel@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Damien Le Moal For devices supporting the command duration limits feature, when a read or write operation has an IO priority specifying one of the IOPRIO_HINT_DEV_DURATION_LIMIT_X hint and the command duration limits feature is enabled, set the command duration limit index field of the command using the hint value. The function ata_set_tf_cdl() is introduced to do this. For unqueued (non NCQ) read and write operations, this function sets the command duration limit index set as the lower 2 bits of the feature field. For queued NCQ read/write commands, the index is set as the lower 2 bits of the auxiliary field. Signed-off-by: Damien Le Moal Co-developed-by: Niklas Cassel Signed-off-by: Niklas Cassel --- drivers/ata/libata-core.c | 42 ++++++++++++++++++++++++++++++++++----- drivers/ata/libata-scsi.c | 3 +-- drivers/ata/libata.h | 2 +- include/linux/libata.h | 1 + 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 62e100fa90e2..90764aeb5446 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -665,13 +665,36 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) return block; } +/* + * Set a taskfile CDL index. + */ +static inline void ata_set_tf_cdl(struct ata_queued_cmd *qc, int ioprio) +{ + struct ata_taskfile *tf = &qc->tf; + unsigned int hint = IOPRIO_PRIO_HINT(ioprio); + int cdl; + + if (hint < IOPRIO_HINT_DEV_DURATION_LIMIT_1 || + hint > IOPRIO_HINT_DEV_DURATION_LIMIT_7) + return; + + cdl = (hint - IOPRIO_HINT_DEV_DURATION_LIMIT_1) + 1; + if (tf->protocol == ATA_PROT_NCQ) + tf->auxiliary |= cdl; + else + tf->feature |= cdl; + + /* Mark this command as having a CDL */ + qc->flags |= ATA_QCFLAG_HAS_CDL; +} + /** * ata_build_rw_tf - Build ATA taskfile for given read/write request * @qc: Metadata associated with the taskfile to build * @block: Block address * @n_block: Number of blocks * @tf_flags: RW/FUA etc... - * @class: IO priority class + * @ioprio: IO priority class and level * * LOCKING: * None. @@ -685,7 +708,7 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) * -EINVAL if the request is invalid. */ int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, - unsigned int tf_flags, int class) + unsigned int tf_flags, int ioprio) { struct ata_taskfile *tf = &qc->tf; struct ata_device *dev = qc->dev; @@ -722,13 +745,22 @@ int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, tf->device |= 1 << 7; if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED && - class == IOPRIO_CLASS_RT) + IOPRIO_PRIO_CLASS(ioprio) == IOPRIO_CLASS_RT) tf->hob_nsect |= ATA_PRIO_HIGH << ATA_SHIFT_PRIO; + + if (dev->flags & ATA_DFLAG_CDL_ENABLED) + ata_set_tf_cdl(qc, ioprio); + } else if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; - /* We need LBA48 for FUA writes */ - if (!(tf->flags & ATA_TFLAG_FUA) && lba_28_ok(block, n_block)) { + if (dev->flags & ATA_DFLAG_CDL_ENABLED) + ata_set_tf_cdl(qc, ioprio); + + /* Both FUA writes and a CDL index require 48-bit commands */ + if (!(tf->flags & ATA_TFLAG_FUA) && + !(qc->flags & ATA_QCFLAG_HAS_CDL) && + lba_28_ok(block, n_block)) { /* use LBA28 */ tf->device |= (block >> 24) & 0xf; } else if (lba_48_ok(block, n_block)) { diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 8dde1cede5ca..ce5c6a49a098 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1546,7 +1546,6 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) struct scsi_cmnd *scmd = qc->scsicmd; const u8 *cdb = scmd->cmnd; struct request *rq = scsi_cmd_to_rq(scmd); - int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq)); unsigned int tf_flags = 0; u64 block; u32 n_block; @@ -1622,7 +1621,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) qc->flags |= ATA_QCFLAG_IO; qc->nbytes = n_block * scmd->device->sector_size; - rc = ata_build_rw_tf(qc, block, n_block, tf_flags, class); + rc = ata_build_rw_tf(qc, block, n_block, tf_flags, req_get_ioprio(rq)); if (likely(rc == 0)) return 0; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 2cd6124a01e8..26aa777a2ad0 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -45,7 +45,7 @@ static inline void ata_force_cbl(struct ata_port *ap) { } extern u64 ata_tf_to_lba(const struct ata_taskfile *tf); extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf); extern int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, - unsigned int tf_flags, int class); + unsigned int tf_flags, int ioprio); extern u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev); extern unsigned ata_exec_internal(struct ata_device *dev, diff --git a/include/linux/libata.h b/include/linux/libata.h index d7fe735e6322..ab8b62036c12 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -209,6 +209,7 @@ enum { ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */ ATA_QCFLAG_QUIET = (1 << 6), /* don't report device error */ ATA_QCFLAG_RETRY = (1 << 7), /* retry after failure */ + ATA_QCFLAG_HAS_CDL = (1 << 8), /* qc has CDL a descriptor set */ ATA_QCFLAG_EH = (1 << 16), /* cmd aborted and owned by EH */ ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */ From patchwork Thu Mar 9 21:55:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 661471 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 92CB0C6FD19 for ; Thu, 9 Mar 2023 21:59:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231417AbjCIV7F (ORCPT ); Thu, 9 Mar 2023 16:59:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51878 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231416AbjCIV5z (ORCPT ); Thu, 9 Mar 2023 16:57:55 -0500 Received: from esa6.hgst.iphmx.com (esa6.hgst.iphmx.com [216.71.154.45]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A3D7B105550; Thu, 9 Mar 2023 13:56:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1678398988; x=1709934988; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9aBVy008VlPFoGqNzpxuuO8Nja9Fnd0wBCRRoZWT4gA=; b=aS/mKTlHYRkb9tD0B6OsG2NKtxL9GgCQvvTrm+ITK1gsF/wkzAk6IltO d6ZZfaUXXjfaZAl9hYPb7NKQYzG0siWDPORYYxwl+sI6aEatTsKXuZ/46 U21U5J+D7Ji7SkMy8NnZ2pMLHpN7Z5YfA1Daq7PS+BT4MkMPWD8/uv1WG 3bfIjEbs2vv04Hh1Y7x1uXu6w6Xz/468+WIZH95MlOK6UyDuZ2GIj1ZFp 8/E2q+rXygJOq84QqQcahgXfyuhG/UKJ2v2Fkb5Q1171uZdlGVu74JSpM qa13lGFmYobVS0ZCJdAh3qChhL8l7HgEpQEUyX6sve7nFbashj8bRjlPc Q==; X-IronPort-AV: E=Sophos;i="5.98,247,1673884800"; d="scan'208";a="225271070" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 10 Mar 2023 05:56:22 +0800 IronPort-SDR: ZKhiHOKaxfHm2sr7izxRvofn6dTGLxLdJr0ic9QCEmUBZYg4DDqqzBeXBE0UDyuFm7cI/KUZfV yz2sDF56FNx/4QhnwKuErqRfF0cASIyQ55QG/zVDXVVB0Ps7iNPD96zWg4V9mzyihmubvaej4o /h0n0pvmERILMsGDEOeehZcWffzha9Iks0hTsKxOysSWZj18k0vShtgiuLj0f4Pc2sfn18WBI5 WO4OIlzis36IIKw8uOhQgGlZX208VovJlk5lXhXIKfclaTxuvB0atZTxfAjwjKlP+33tTk58d6 WT0= Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 09 Mar 2023 13:07:15 -0800 IronPort-SDR: 4FKFvnJ9MlAXp4l6NWXK/aIWIc02elulB6f8/rr8bs7NfXULAk/5N77zvVwHogbWyu5ehqxoRK JUuurDUAXAHJFm+rNFZZoEcjo1s1vW2EOyuHKDooKZQDPL9MbkC+o+JrV0UNl6VkKW6utkbRX4 agbG94i8rNgPZYk2qT8rILDxYC7tt1AS9l7rBCy/SzM246Mz5N4DdJ+TkMxfvRwmiRhzML+sjk w4ehAsONX0Fk/Lcv5Jr33CG7u3duthXSThky8JShXmVJVJZZvPSgOJ5gvQ2qH6RUUFIERJ4ezS XWg= WDCIronportException: Internal Received: from unknown (HELO x1-carbon.wdc.com) ([10.225.164.41]) by uls-op-cesaip01.wdc.com with ESMTP; 09 Mar 2023 13:56:21 -0800 From: Niklas Cassel To: Damien Le Moal Cc: Christoph Hellwig , Hannes Reinecke , linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, linux-block@vger.kernel.org, Niklas Cassel Subject: [PATCH v4 19/19] ata: libata: handle completion of CDL commands using policy 0xD Date: Thu, 9 Mar 2023 22:55:11 +0100 Message-Id: <20230309215516.3800571-20-niklas.cassel@wdc.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230309215516.3800571-1-niklas.cassel@wdc.com> References: <20230309215516.3800571-1-niklas.cassel@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org A CDL timeout for policy 0xF is defined as a NCQ error, just with a CDL specific sk/asc/ascq in the sense data. Therefore, the existing code in libata does not need to be modified to handle a policy 0xF CDL timeout. For Command Duration Limits policy 0xD: The device shall complete the command without error with the additional sense code set to DATA CURRENTLY UNAVAILABLE. Since a CDL timeout for policy 0xD is not an error, we cannot use the NCQ Command Error log (10h). Instead, we need to read the Sense Data for Successful NCQ Commands log (0Fh). In the success case, just like in the error case, we cannot simply read a log page from the interrupt handler itself, since reading a log page involves sending a READ LOG DMA EXT or READ LOG EXT command. Therefore, we add a new EH action ATA_EH_GET_SUCCESS_SENSE. When a command completes without error, and when the ATA_SENSE bit is set, this new action is set as pending, and EH is scheduled. This way, similar to the NCQ error case, the log page will be read from EH context. An alternative would have been to add a new kthread or workqueue to handle this. However, extending EH can be done with minimal changes and avoids the need to synchronize a new kthread/workqueue with EH. Co-developed-by: Damien Le Moal Signed-off-by: Damien Le Moal Signed-off-by: Niklas Cassel Reviewed-by: Hannes Reinecke --- drivers/ata/libata-core.c | 88 +++++++++++++++++++++++++++++++- drivers/ata/libata-eh.c | 105 +++++++++++++++++++++++++++++++++++++- drivers/ata/libata-sata.c | 92 +++++++++++++++++++++++++++++++++ include/linux/ata.h | 3 ++ include/linux/libata.h | 11 +++- 5 files changed, 295 insertions(+), 4 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 90764aeb5446..44ac541c4472 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -684,8 +684,12 @@ static inline void ata_set_tf_cdl(struct ata_queued_cmd *qc, int ioprio) else tf->feature |= cdl; - /* Mark this command as having a CDL */ - qc->flags |= ATA_QCFLAG_HAS_CDL; + /* + * Mark this command as having a CDL and request the result + * task file so that we can inspect the sense data available + * bit on completion. + */ + qc->flags |= ATA_QCFLAG_HAS_CDL | ATA_QCFLAG_RESULT_TF; } /** @@ -2430,6 +2434,24 @@ static void ata_dev_config_cdl(struct ata_device *dev) ata_dev_warn(dev, "Command duration guideline is not supported\n"); + /* + * We must have support for the sense data for successful NCQ commands + * log indicated by the successful NCQ command sense data supported bit. + */ + val = get_unaligned_le64(&ap->sector_buf[8]); + if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(47))) { + ata_dev_warn(dev, + "CDL supported but Successful NCQ Command Sense Data is not supported\n"); + goto not_supported; + } + + /* Without NCQ autosense, the successful NCQ commands log is useless. */ + if (!ata_id_has_ncq_autosense(dev->id)) { + ata_dev_warn(dev, + "CDL supported but NCQ autosense is not supported\n"); + goto not_supported; + } + /* * If CDL is marked as enabled, make sure the feature is enabled too. * Conversely, if CDL is disabled, make sure the feature is turned off. @@ -2464,6 +2486,35 @@ static void ata_dev_config_cdl(struct ata_device *dev) } } + /* + * While CDL itself has to be enabled using sysfs, CDL requires that + * sense data for successful NCQ commands is enabled to work properly. + * Just like ata_dev_config_sense_reporting(), enable it unconditionally + * if supported. + */ + if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(18))) { + err_mask = ata_dev_set_feature(dev, + SETFEATURE_SENSE_DATA_SUCC_NCQ, 0x1); + if (err_mask) { + ata_dev_warn(dev, + "failed to enable Sense Data for successful NCQ commands, Emask 0x%x\n", + err_mask); + goto not_supported; + } + } + + /* + * Allocate a buffer to handle reading the sense data for successful + * NCQ Commands log page for commands using a CDL with one of the limit + * policy set to 0xD (successful completion with sense data available + * bit set). + */ + if (!ap->ncq_sense_buf) { + ap->ncq_sense_buf = kmalloc(ATA_LOG_SENSE_NCQ_SIZE, GFP_KERNEL); + if (!ap->ncq_sense_buf) + goto not_supported; + } + /* * Command duration limits is supported: cache the CDL log page 18h * (command duration descriptors). @@ -2481,6 +2532,8 @@ static void ata_dev_config_cdl(struct ata_device *dev) not_supported: dev->flags &= ~(ATA_DFLAG_CDL | ATA_DFLAG_CDL_ENABLED); + kfree(ap->ncq_sense_buf); + ap->ncq_sense_buf = NULL; } static int ata_dev_config_lba(struct ata_device *dev) @@ -4884,6 +4937,36 @@ void ata_qc_complete(struct ata_queued_cmd *qc) fill_result_tf(qc); trace_ata_qc_complete_done(qc); + + /* + * For CDL commands that completed without an error, check if + * we have sense data (ATA_SENSE is set). If we do, then the + * command may have been aborted by the device due to a limit + * timeout using the policy 0xD. For these commands, invoke EH + * to get the command sense data. + */ + if (qc->result_tf.status & ATA_SENSE && + ((ata_is_ncq(qc->tf.protocol) && + dev->flags & ATA_DFLAG_CDL_ENABLED) || + (!(ata_is_ncq(qc->tf.protocol) && + ata_id_sense_reporting_enabled(dev->id))))) { + /* + * Tell SCSI EH to not overwrite scmd->result even if + * this command is finished with result SAM_STAT_GOOD. + */ + qc->scsicmd->flags |= SCMD_FORCE_EH_SUCCESS; + qc->flags |= ATA_QCFLAG_EH_SUCCESS_CMD; + ehi->dev_action[dev->devno] |= ATA_EH_GET_SUCCESS_SENSE; + + /* + * set pending so that ata_qc_schedule_eh() does not + * trigger fast drain, and freeze the port. + */ + ap->pflags |= ATA_PFLAG_EH_PENDING; + ata_qc_schedule_eh(qc); + return; + } + /* Some commands need post-processing after successful * completion. */ @@ -5516,6 +5599,7 @@ static void ata_host_release(struct kref *kref) kfree(ap->pmp_link); kfree(ap->slave_link); + kfree(ap->ncq_sense_buf); kfree(ap); host->ports[i] = NULL; } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 598ae07195b6..05af292eb8ce 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1917,6 +1917,99 @@ static inline bool ata_eh_quiet(struct ata_queued_cmd *qc) return qc->flags & ATA_QCFLAG_QUIET; } +static int ata_eh_read_sense_success_non_ncq(struct ata_link *link) +{ + struct ata_port *ap = link->ap; + struct ata_queued_cmd *qc; + + qc = __ata_qc_from_tag(ap, link->active_tag); + if (!qc) + return -EIO; + + if (!(qc->flags & ATA_QCFLAG_EH) || + !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) || + qc->err_mask) + return -EIO; + + if (!ata_eh_request_sense(qc)) + return -EIO; + + /* + * If we have sense data, call scsi_check_sense() in order to set the + * correct SCSI ML byte (if any). No point in checking the return value, + * since the command has already completed successfully. + */ + scsi_check_sense(qc->scsicmd); + + return 0; +} + +static void ata_eh_get_success_sense(struct ata_link *link) +{ + struct ata_eh_context *ehc = &link->eh_context; + struct ata_device *dev = link->device; + struct ata_port *ap = link->ap; + struct ata_queued_cmd *qc; + int tag, ret = 0; + + if (!(ehc->i.dev_action[dev->devno] & ATA_EH_GET_SUCCESS_SENSE)) + return; + + /* if frozen, we can't do much */ + if (ata_port_is_frozen(ap)) { + ata_dev_warn(dev, + "successful sense data available but port frozen\n"); + goto out; + } + + /* + * If the link has sactive set, then we have outstanding NCQ commands + * and have to read the Successful NCQ Commands log to get the sense + * data. Otherwise, we are dealing with a non-NCQ command and use + * request sense ext command to retrieve the sense data. + */ + if (link->sactive) + ret = ata_eh_read_sense_success_ncq_log(link); + else + ret = ata_eh_read_sense_success_non_ncq(link); + if (ret) + goto out; + + ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE); + return; + +out: + /* + * If we failed to get sense data for a successful command that ought to + * have sense data, we cannot simply return BLK_STS_OK to user space. + * This is because we can't know if the sense data that we couldn't get + * was actually "DATA CURRENTLY UNAVAILABLE". Reporting such a command + * as success to user space would result in a silent data corruption. + * Thus, add a bogus ABORTED_COMMAND sense data to such commands, such + * that SCSI will report these commands as BLK_STS_IOERR to user space. + */ + ata_qc_for_each_raw(ap, qc, tag) { + if (!(qc->flags & ATA_QCFLAG_EH) || + !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) || + qc->err_mask || + ata_dev_phys_link(qc->dev) != link) + continue; + + /* We managed to get sense for this success command, skip. */ + if (qc->flags & ATA_QCFLAG_SENSE_VALID) + continue; + + /* This success command did not have any sense data, skip. */ + if (!(qc->result_tf.status & ATA_SENSE)) + continue; + + /* This success command had sense data, but we failed to get. */ + ata_scsi_set_sense(dev, qc->scsicmd, ABORTED_COMMAND, 0, 0); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + } + ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE); +} + /** * ata_eh_link_autopsy - analyze error and determine recovery action * @link: host link to perform autopsy on @@ -1957,6 +2050,14 @@ static void ata_eh_link_autopsy(struct ata_link *link) /* analyze NCQ failure */ ata_eh_analyze_ncq_error(link); + /* + * Check if this was a successful command that simply needs sense data. + * Since the sense data is not part of the completion, we need to fetch + * it using an additional command. Since this can't be done from irq + * context, the sense data for successful commands are fetched by EH. + */ + ata_eh_get_success_sense(link); + /* any real error trumps AC_ERR_OTHER */ if (ehc->i.err_mask & ~AC_ERR_OTHER) ehc->i.err_mask &= ~AC_ERR_OTHER; @@ -1966,6 +2067,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) ata_qc_for_each_raw(ap, qc, tag) { if (!(qc->flags & ATA_QCFLAG_EH) || qc->flags & ATA_QCFLAG_RETRY || + qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD || ata_dev_phys_link(qc->dev) != link) continue; @@ -3825,7 +3927,8 @@ void ata_eh_finish(struct ata_port *ap) else ata_eh_qc_complete(qc); } else { - if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + if (qc->flags & ATA_QCFLAG_SENSE_VALID || + qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) { ata_eh_qc_complete(qc); } else { /* feed zero TF to sense generation */ diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index 57cb33060c9d..7de4d8901fac 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include #include "libata.h" #include "libata-transport.h" @@ -1408,6 +1410,95 @@ static int ata_eh_read_log_10h(struct ata_device *dev, return 0; } +/** + * ata_eh_read_sense_success_ncq_log - Read the sense data for successful + * NCQ commands log + * @link: ATA link to get sense data for + * + * Read the sense data for successful NCQ commands log page to obtain + * sense data for all NCQ commands that completed successfully with + * the sense data available bit set. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ata_eh_read_sense_success_ncq_log(struct ata_link *link) +{ + struct ata_device *dev = link->device; + struct ata_port *ap = dev->link->ap; + u8 *buf = ap->ncq_sense_buf; + struct ata_queued_cmd *qc; + unsigned int err_mask, tag; + u8 *sense, sk = 0, asc = 0, ascq = 0; + u64 sense_valid, val; + int ret = 0; + + err_mask = ata_read_log_page(dev, ATA_LOG_SENSE_NCQ, 0, buf, 2); + if (err_mask) { + ata_dev_err(dev, + "Failed to read Sense Data for Successful NCQ Commands log\n"); + return -EIO; + } + + /* Check the log header */ + val = get_unaligned_le64(&buf[0]); + if ((val & 0xffff) != 1 || ((val >> 16) & 0xff) != 0x0f) { + ata_dev_err(dev, + "Invalid Sense Data for Successful NCQ Commands log\n"); + return -EIO; + } + + sense_valid = (u64)buf[8] | ((u64)buf[9] << 8) | + ((u64)buf[10] << 16) | ((u64)buf[11] << 24); + + ata_qc_for_each_raw(ap, qc, tag) { + if (!(qc->flags & ATA_QCFLAG_EH) || + !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) || + qc->err_mask || + ata_dev_phys_link(qc->dev) != link) + continue; + + /* + * If the command does not have any sense data, clear ATA_SENSE. + * Keep ATA_QCFLAG_EH_SUCCESS_CMD so that command is finished. + */ + if (!(sense_valid & (1ULL << tag))) { + qc->result_tf.status &= ~ATA_SENSE; + continue; + } + + sense = &buf[32 + 24 * tag]; + sk = sense[0]; + asc = sense[1]; + ascq = sense[2]; + + if (!ata_scsi_sense_is_valid(sk, asc, ascq)) { + ret = -EIO; + continue; + } + + /* Set sense without also setting scsicmd->result */ + scsi_build_sense_buffer(dev->flags & ATA_DFLAG_D_SENSE, + qc->scsicmd->sense_buffer, sk, + asc, ascq); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + + /* + * If we have sense data, call scsi_check_sense() in order to + * set the correct SCSI ML byte (if any). No point in checking + * the return value, since the command has already completed + * successfully. + */ + scsi_check_sense(qc->scsicmd); + } + + return ret; +} +EXPORT_SYMBOL_GPL(ata_eh_read_sense_success_ncq_log); + /** * ata_eh_analyze_ncq_error - analyze NCQ error * @link: ATA link to analyze NCQ error for @@ -1488,6 +1579,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) ata_qc_for_each_raw(ap, qc, tag) { if (!(qc->flags & ATA_QCFLAG_EH) || + qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD || ata_dev_phys_link(qc->dev) != link) continue; diff --git a/include/linux/ata.h b/include/linux/ata.h index a59b17d6ad11..2e2e22362096 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -326,6 +326,8 @@ enum { ATA_LOG_CDL = 0x18, ATA_LOG_CDL_SIZE = ATA_SECT_SIZE, ATA_LOG_IDENTIFY_DEVICE = 0x30, + ATA_LOG_SENSE_NCQ = 0x0F, + ATA_LOG_SENSE_NCQ_SIZE = ATA_SECT_SIZE * 2, ATA_LOG_CONCURRENT_POSITIONING_RANGES = 0x47, /* Identify device log pages: */ @@ -432,6 +434,7 @@ enum { SATA_DEVSLP = 0x09, /* Device Sleep */ SETFEATURE_SENSE_DATA = 0xC3, /* Sense Data Reporting feature */ + SETFEATURE_SENSE_DATA_SUCC_NCQ = 0xC4, /* Sense Data for successful NCQ commands */ /* feature values for SET_MAX */ ATA_SET_MAX_ADDR = 0x00, diff --git a/include/linux/libata.h b/include/linux/libata.h index ab8b62036c12..70ac635fe5d7 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -214,6 +214,7 @@ enum { ATA_QCFLAG_EH = (1 << 16), /* cmd aborted and owned by EH */ ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */ ATA_QCFLAG_EH_SCHEDULED = (1 << 18), /* EH scheduled (obsolete) */ + ATA_QCFLAG_EH_SUCCESS_CMD = (1 << 19), /* EH should fetch sense for this successful cmd */ /* host set flags */ ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host only */ @@ -312,8 +313,10 @@ enum { ATA_EH_RESET = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, ATA_EH_ENABLE_LINK = (1 << 3), ATA_EH_PARK = (1 << 5), /* unload heads and stop I/O */ + ATA_EH_GET_SUCCESS_SENSE = (1 << 6), /* Get sense data for successful cmd */ - ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK, + ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK | + ATA_EH_GET_SUCCESS_SENSE, ATA_EH_ALL_ACTIONS = ATA_EH_REVALIDATE | ATA_EH_RESET | ATA_EH_ENABLE_LINK, @@ -867,6 +870,7 @@ struct ata_port { struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */ #endif /* owned by EH */ + u8 *ncq_sense_buf; u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned; }; @@ -1185,6 +1189,7 @@ extern int sata_link_hardreset(struct ata_link *link, bool *online, int (*check_ready)(struct ata_link *)); extern int sata_link_resume(struct ata_link *link, const unsigned long *params, unsigned long deadline); +extern int ata_eh_read_sense_success_ncq_log(struct ata_link *link); extern void ata_eh_analyze_ncq_error(struct ata_link *link); #else static inline const unsigned long * @@ -1222,6 +1227,10 @@ static inline int sata_link_resume(struct ata_link *link, { return -EOPNOTSUPP; } +static inline int ata_eh_read_sense_success_ncq_log(struct ata_link *link) +{ + return -EOPNOTSUPP; +} static inline void ata_eh_analyze_ncq_error(struct ata_link *link) { } #endif extern int sata_link_debounce(struct ata_link *link,