From patchwork Sun Jan 7 18:02:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phillip Susi X-Patchwork-Id: 1883414 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2604:1380:4601:e00::3; helo=am.mirrors.kernel.org; envelope-from=linux-ide+bounces-166-incoming=patchwork.ozlabs.org@vger.kernel.org; receiver=patchwork.ozlabs.org) Received: from am.mirrors.kernel.org (am.mirrors.kernel.org [IPv6:2604:1380:4601:e00::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T7Q670Pgpz1yPT for ; Mon, 8 Jan 2024 05:03:10 +1100 (AEDT) Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id AFCFD1F213C1 for ; Sun, 7 Jan 2024 18:03:08 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C10E913AFD; Sun, 7 Jan 2024 18:03:03 +0000 (UTC) X-Original-To: linux-ide@vger.kernel.org Received: from vps.thesusis.net (vps.thesusis.net [34.202.238.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 682A313FE0 for ; Sun, 7 Jan 2024 18:03:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=thesusis.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=thesusis.net Received: by vps.thesusis.net (Postfix, from userid 1000) id 9E42315231F; Sun, 7 Jan 2024 13:03:01 -0500 (EST) From: Phillip Susi To: linux-ide@vger.kernel.org Cc: Damien Le Moal , Sergey Shtylyov , Phillip Susi Subject: [PATCH 1/3] libata: avoid waking disk for several commands Date: Sun, 7 Jan 2024 13:02:56 -0500 Message-Id: <20240107180258.360886-2-phill@thesusis.net> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240107180258.360886-1-phill@thesusis.net> References: <87msthdo11.fsf@vps.thesusis.net> <20240107180258.360886-1-phill@thesusis.net> Precedence: bulk X-Mailing-List: linux-ide@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When a disk is in SLEEP mode it can not respond to any any commands. Several commands are simply a NOOP to a disk that is in standby mode, but when a disk is in SLEEP mode, they frequencly cause the disk to spin up for no reason. To avoid this, complete these commands in libata without waking the disk. These commands are: CHECK POWER MODE FLUSH CACHE SLEEP STANDBY IMMEDIATE IDENTIFY If we know the disk is sleeping, we don't need to wake it up to find out if it is in standby, so just pretend it is in standby. While asleep, there's no dirty pages in the cache, so there's no need to flush it. There's no point in waking a disk from sleep just to put it back to sleep. We also have a cache of the IDENTIFY information so just return that instead of waking the disk. --- drivers/ata/libata-core.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 09ed67772fae..6c5269de4bf2 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5040,6 +5040,26 @@ void ata_qc_issue(struct ata_queued_cmd *qc) /* if device is sleeping, schedule reset and abort the link */ if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) { + switch (qc->tf.command) + { + case ATA_CMD_CHK_POWER: + case ATA_CMD_SLEEP: + case ATA_CMD_FLUSH: + case ATA_CMD_FLUSH_EXT: + case ATA_CMD_STANDBYNOW1: + if (qc->tf.command == ATA_CMD_ID_ATA) + { + /* only fake the reply for IDENTIFY if it is from userspace */ + if (ata_tag_internal(qc->tag)) + break; + sg_copy_from_buffer(qc->sg, 1, qc->dev->id, 2 * ATA_ID_WORDS); + } + /* fake reply to avoid waking drive */ + qc->flags |= ATA_QCFLAG_RTF_FILLED; + qc->result_tf.nsect = 0; + ata_qc_complete(qc); + return; + } link->eh_info.action |= ATA_EH_RESET; ata_ehi_push_desc(&link->eh_info, "waking up from sleep"); ata_link_abort(link); From patchwork Sun Jan 7 18:02:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phillip Susi X-Patchwork-Id: 1883413 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=139.178.88.99; helo=sv.mirrors.kernel.org; envelope-from=linux-ide+bounces-167-incoming=patchwork.ozlabs.org@vger.kernel.org; receiver=patchwork.ozlabs.org) Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org [139.178.88.99]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T7Q660z2rz1yPH for ; Mon, 8 Jan 2024 05:03:10 +1100 (AEDT) Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 2022F281D7A for ; Sun, 7 Jan 2024 18:03:08 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EF75613FEB; Sun, 7 Jan 2024 18:03:03 +0000 (UTC) X-Original-To: linux-ide@vger.kernel.org Received: from vps.thesusis.net (vps.thesusis.net [34.202.238.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6833713FE5 for ; Sun, 7 Jan 2024 18:03:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=thesusis.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=thesusis.net Received: by vps.thesusis.net (Postfix, from userid 1000) id A7F55152323; Sun, 7 Jan 2024 13:03:01 -0500 (EST) From: Phillip Susi To: linux-ide@vger.kernel.org Cc: Damien Le Moal , Sergey Shtylyov , Phillip Susi Subject: [PATCH 2/3] libata: only wake a drive once on system resume Date: Sun, 7 Jan 2024 13:02:57 -0500 Message-Id: <20240107180258.360886-3-phill@thesusis.net> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240107180258.360886-1-phill@thesusis.net> References: <87msthdo11.fsf@vps.thesusis.net> <20240107180258.360886-1-phill@thesusis.net> Precedence: bulk X-Mailing-List: linux-ide@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In the event that more than one pass of EH is needed during system resume, only request the drive be started once ( if the first time worked ). --- drivers/ata/libata-core.c | 9 +++++---- drivers/ata/libata-eh.c | 8 +++----- drivers/ata/libata.h | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 6c5269de4bf2..ef6a2349a6f8 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2080,7 +2080,7 @@ static bool ata_dev_power_is_active(struct ata_device *dev) * LOCKING: * Kernel thread context (may sleep). */ -void ata_dev_power_set_active(struct ata_device *dev) +unsigned int ata_dev_power_set_active(struct ata_device *dev) { struct ata_taskfile tf; unsigned int err_mask; @@ -2090,14 +2090,14 @@ void ata_dev_power_set_active(struct ata_device *dev) * if supported by the device. */ if (!ata_dev_power_init_tf(dev, &tf, true)) - return; + return AC_ERR_OK; /* * Check the device power state & condition and force a spinup with * VERIFY command only if the drive is not already ACTIVE or IDLE. */ if (ata_dev_power_is_active(dev)) - return; + return AC_ERR_OK; ata_dev_notice(dev, "Entering active power mode\n"); @@ -2105,6 +2105,7 @@ void ata_dev_power_set_active(struct ata_device *dev) if (err_mask) ata_dev_err(dev, "VERIFY failed (err_mask=0x%x)\n", err_mask); + return err_mask; } /** @@ -5277,7 +5278,7 @@ static int ata_port_pm_poweroff(struct device *dev) static void ata_port_resume(struct ata_port *ap, pm_message_t mesg, bool async) { - ata_port_request_pm(ap, mesg, ATA_EH_RESET, + ata_port_request_pm(ap, mesg, ATA_EH_RESET | ATA_EH_SET_ACTIVE, ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, async); } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index b0d6e69c4a5b..799a1b8bc384 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -710,10 +710,6 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap) ehc->saved_xfer_mode[devno] = dev->xfer_mode; if (ata_ncq_enabled(dev)) ehc->saved_ncq_enabled |= 1 << devno; - - /* If we are resuming, wake up the device */ - if (ap->pflags & ATA_PFLAG_RESUMING) - ehc->i.dev_action[devno] |= ATA_EH_SET_ACTIVE; } } @@ -3853,7 +3849,9 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, */ ata_for_each_dev(dev, link, ENABLED) { if (ehc->i.dev_action[dev->devno] & ATA_EH_SET_ACTIVE) { - ata_dev_power_set_active(dev); + unsigned int err_mask = ata_dev_power_set_active(dev); + if (err_mask) + link->eh_info.dev_action[dev->devno] |= ATA_EH_SET_ACTIVE; ata_eh_done(link, dev, ATA_EH_SET_ACTIVE); } } diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 5c685bb1939e..43ad1ef9b63a 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -65,7 +65,7 @@ extern int ata_dev_configure(struct ata_device *dev); extern bool ata_dev_power_init_tf(struct ata_device *dev, struct ata_taskfile *tf, bool set_active); extern void ata_dev_power_set_standby(struct ata_device *dev); -extern void ata_dev_power_set_active(struct ata_device *dev); +extern unsigned int ata_dev_power_set_active(struct ata_device *dev); extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit); extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); extern unsigned int ata_dev_set_feature(struct ata_device *dev, From patchwork Sun Jan 7 18:02:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phillip Susi X-Patchwork-Id: 1883412 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=147.75.48.161; helo=sy.mirrors.kernel.org; envelope-from=linux-ide+bounces-168-incoming=patchwork.ozlabs.org@vger.kernel.org; receiver=patchwork.ozlabs.org) Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org [147.75.48.161]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T7Q663Qv6z1yPK for ; Mon, 8 Jan 2024 05:03:10 +1100 (AEDT) Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id E14B1B2149C for ; Sun, 7 Jan 2024 18:03:09 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9032913FEA; Sun, 7 Jan 2024 18:03:04 +0000 (UTC) X-Original-To: linux-ide@vger.kernel.org Received: from vps.thesusis.net (vps.thesusis.net [34.202.238.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6830113FE4 for ; Sun, 7 Jan 2024 18:03:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=thesusis.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=thesusis.net Received: by vps.thesusis.net (Postfix, from userid 1000) id AF28F152326; Sun, 7 Jan 2024 13:03:01 -0500 (EST) From: Phillip Susi To: linux-ide@vger.kernel.org Cc: Damien Le Moal , Sergey Shtylyov , Phillip Susi Subject: [PATCH 3/3] libata: don't start PuiS disks on resume Date: Sun, 7 Jan 2024 13:02:58 -0500 Message-Id: <20240107180258.360886-4-phill@thesusis.net> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240107180258.360886-1-phill@thesusis.net> References: <87msthdo11.fsf@vps.thesusis.net> <20240107180258.360886-1-phill@thesusis.net> Precedence: bulk X-Mailing-List: linux-ide@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Disks with Power Up In Standby enabled that required the SET FEATURES command to start up were being issued the command during resume. Recently this was extended to include PuiS disks that don't require the SET FEATURES command. Suppress this and leave the disk in standby until the disk is actually accessed. --- drivers/ata/libata-core.c | 32 ++++++++++++++++++++++++++++---- drivers/ata/libata-eh.c | 12 +++++++++++- drivers/ata/libata.h | 1 + include/linux/libata.h | 1 + 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ef6a2349a6f8..f758fc88ac19 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1912,7 +1912,30 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, goto err_out; } - if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) { + if (flags & ATA_READID_NOSTART && id[2] == 0x37c8) + { + /* + * The drive has powered up in standby, and returned incomplete IDENTIFY info + * so we can't revalidate it yet. We have also been asked to avoid starting the + * drive, so stop here and leave the drive asleep and the EH pending, to be + * restarted on later I/O request + */ +#if 0 + ata_tf_init(dev, &tf); + tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; + tf.protocol = ATA_PROT_NODATA; + tf.command = ATA_CMD_SLEEP; + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); + ata_dev_info(dev, "PuiS detected, putting drive to sleep"); +#else + dev->flags |= ATA_DFLAG_SLEEPING; + ata_dev_info(dev, "PuiS detected, leaving drive in standby"); +#endif + return -EAGAIN; + } + + if (!(flags & ATA_READID_NOSTART) && + !tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) { tried_spinup = 1; /* * Drive powered-up in standby mode, and requires a specific @@ -3969,6 +3992,8 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, /* re-read ID */ rc = ata_dev_reread_id(dev, readid_flags); + if (rc == -EAGAIN) + return rc; if (rc) goto fail; @@ -5241,8 +5266,7 @@ static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg, * http://thread.gmane.org/gmane.linux.ide/46764 */ ata_port_request_pm(ap, mesg, 0, - ATA_EHI_QUIET | ATA_EHI_NO_AUTOPSY | - ATA_EHI_NO_RECOVERY, + ATA_EHI_QUIET | ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY, async); } @@ -5279,7 +5303,7 @@ static void ata_port_resume(struct ata_port *ap, pm_message_t mesg, bool async) { ata_port_request_pm(ap, mesg, ATA_EH_RESET | ATA_EH_SET_ACTIVE, - ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, + ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET | ATA_EHI_NOSTART, async); } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 799a1b8bc384..e45e60112951 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -22,6 +22,7 @@ #include #include #include "../scsi/scsi_transport_api.h" +#include #include @@ -3046,6 +3047,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, if (ehc->i.flags & ATA_EHI_DID_RESET) readid_flags |= ATA_READID_POSTRESET; + if (ehc->i.flags & ATA_EHI_NOSTART) + readid_flags |= ATA_READID_NOSTART; if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) { WARN_ON(dev->class == ATA_DEV_PMP); @@ -3075,8 +3078,15 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, ata_eh_about_to_do(link, dev, ATA_EH_REVALIDATE); rc = ata_dev_revalidate(dev, ehc->classes[dev->devno], readid_flags); - if (rc) + if (rc == -EAGAIN) { + rc = 0; /* start required but suppressed, handle later */ + ehc->i.dev_action[dev->devno] &= ~ATA_EH_SET_ACTIVE; + continue; + } + else if (rc) + { goto err; + } ata_eh_done(link, dev, ATA_EH_REVALIDATE); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 43ad1ef9b63a..cff3facad055 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -19,6 +19,7 @@ enum { /* flags for ata_dev_read_id() */ ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */ + ATA_READID_NOSTART = (1 << 1), /* do not start drive */ /* selector for ata_down_xfermask_limit() */ ATA_DNXFER_PIO = 0, /* speed down PIO */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 1dbb14daccfa..50d6fa933946 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -328,6 +328,7 @@ enum { /* ata_eh_info->flags */ ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ + ATA_EHI_NOSTART = (1 << 1), /* don't start the disk */ ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */ ATA_EHI_QUIET = (1 << 3), /* be quiet */ ATA_EHI_NO_RECOVERY = (1 << 4), /* no recovery */