From nobody Wed Nov 19 20:21:11 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 170238364104735.23066980898852; Tue, 12 Dec 2023 04:20:41 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rD1jA-00058x-Jb; Tue, 12 Dec 2023 07:19:08 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rD1j9-00058Z-A9; Tue, 12 Dec 2023 07:19:07 -0500 Received: from isrv.corpit.ru ([86.62.121.231]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rD1it-0000EJ-Lh; Tue, 12 Dec 2023 07:19:07 -0500 Received: from tsrv.corpit.ru (tsrv.tls.msk.ru [192.168.177.2]) by isrv.corpit.ru (Postfix) with ESMTP id EED523AEF6; Tue, 12 Dec 2023 15:18:48 +0300 (MSK) Received: from tls.msk.ru (mjt.wg.tls.msk.ru [192.168.177.130]) by tsrv.corpit.ru (Postfix) with SMTP id B1C173B944; Tue, 12 Dec 2023 15:18:31 +0300 (MSK) Received: (nullmailer pid 1003407 invoked by uid 1000); Tue, 12 Dec 2023 12:18:31 -0000 From: Michael Tokarev To: qemu-devel@nongnu.org Cc: qemu-stable@nongnu.org, Niklas Cassel , Marcin Juszkiewicz , Kevin Wolf , Michael Tokarev Subject: [Stable-8.1.4 03/31] hw/ide/ahci: fix legacy software reset Date: Tue, 12 Dec 2023 15:17:51 +0300 Message-Id: <20231212121831.1003318-3-mjt@tls.msk.ru> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=86.62.121.231; envelope-from=mjt@tls.msk.ru; helo=isrv.corpit.ru X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01, T_SPF_HELO_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1702383643219100003 Content-Type: text/plain; charset="utf-8" From: Niklas Cassel Legacy software contains a standard mechanism for generating a reset to a Serial ATA device - setting the SRST (software reset) bit in the Device Control register. Serial ATA has a more robust mechanism called COMRESET, also referred to as port reset. A port reset is the preferred mechanism for error recovery and should be used in place of software reset. Commit e2a5d9b3d9c3 ("hw/ide/ahci: simplify and document PxCI handling") (mjt: 16cc9594d23d in stable-8.1 series, v8.1.1) improved the handling of PxCI, such that PxCI gets cleared after handling a non-NCQ, or NCQ command (instead of incorrectly clearing PxCI after receiving anything - even a FIS that failed to parse, which should NOT clear PxCI, so that you can see which command slot that caused an error). However, simply clearing PxCI after a non-NCQ, or NCQ command, is not enough, we also need to clear PxCI when receiving a SRST in the Device Control register. A legacy software reset is performed by the host sending two H2D FISes, the first H2D FIS asserts SRST, and the second H2D FIS deasserts SRST. The first H2D FIS will not get a D2H reply, and requires the FIS to have the C bit set to one, such that the HBA itself will clear the bit in PxCI. The second H2D FIS will get a D2H reply once the diagnostic is completed. The clearing of the bit in PxCI for this command should ideally be done in ahci_init_d2h() (if it was a legacy software reset that caused the reset (a COMRESET does not use a command slot)). However, since the reset value for PxCI is 0, modify ahci_reset_port() to actually clear PxCI to 0, that way we can avoid complex logic in ahci_init_d2h(). This fixes an issue for FreeBSD where the device would fail to reset. The problem was not noticed in Linux, because Linux uses a COMRESET instead of a legacy software reset by default. Fixes: e2a5d9b3d9c3 ("hw/ide/ahci: simplify and document PxCI handling") Reported-by: Marcin Juszkiewicz Signed-off-by: Niklas Cassel Message-ID: <20231108222657.117984-1-nks@flawful.org> Reviewed-by: Kevin Wolf Tested-by: Marcin Juszkiewicz Signed-off-by: Kevin Wolf (cherry picked from commit eabb921250666501ae78714b60090200b639fcfe) Signed-off-by: Michael Tokarev (mjt: mention 16cc9594d23d for stable-8.1) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index d0a774bc17..1718b7e902 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -623,9 +623,13 @@ static void ahci_init_d2h(AHCIDevice *ad) return; } =20 + /* + * For simplicity, do not call ahci_clear_cmd_issue() for this + * ahci_write_fis_d2h(). (The reset value for PxCI is 0.) + */ if (ahci_write_fis_d2h(ad, true)) { ad->init_d2h_sent =3D true; - /* We're emulating receiving the first Reg H2D Fis from the device; + /* We're emulating receiving the first Reg D2H FIS from the device; * Update the SIG register, but otherwise proceed as normal. */ pr->sig =3D ((uint32_t)ide_state->hcyl << 24) | (ide_state->lcyl << 16) | @@ -663,6 +667,7 @@ static void ahci_reset_port(AHCIState *s, int port) pr->scr_act =3D 0; pr->tfdata =3D 0x7F; pr->sig =3D 0xFFFFFFFF; + pr->cmd_issue =3D 0; d->busy_slot =3D -1; d->init_d2h_sent =3D false; =20 @@ -1243,10 +1248,30 @@ static void handle_reg_h2d_fis(AHCIState *s, int po= rt, case STATE_RUN: if (cmd_fis[15] & ATA_SRST) { s->dev[port].port_state =3D STATE_RESET; + /* + * When setting SRST in the first H2D FIS in the reset seq= uence, + * the device does not send a D2H FIS. Host software thus = has to + * set the "Clear Busy upon R_OK" bit such that PxCI (and = BUSY) + * gets cleared. See AHCI 1.3.1, section 10.4.1 Software R= eset. + */ + if (opts & AHCI_CMD_CLR_BUSY) { + ahci_clear_cmd_issue(ad, slot); + } } break; case STATE_RESET: if (!(cmd_fis[15] & ATA_SRST)) { + /* + * When clearing SRST in the second H2D FIS in the reset + * sequence, the device will execute diagnostics. When thi= s is + * done, the device will send a D2H FIS with the good stat= us. + * See SATA 3.5a Gold, section 11.4 Software reset protoco= l. + * + * This D2H FIS is the first D2H FIS received from the dev= ice, + * and is received regardless if the reset was performed b= y a + * COMRESET or by setting and clearing the SRST bit. There= fore, + * the logic for this is found in ahci_init_d2h() and not = here. + */ ahci_reset_port(s, port); } break; --=20 2.39.2