From owner-svn-src-stable@freebsd.org Thu Aug 8 21:44:38 2019 Return-Path: Delivered-To: svn-src-stable@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 34899B4170; Thu, 8 Aug 2019 21:44:38 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 464MN60KlXz3C9S; Thu, 8 Aug 2019 21:44:38 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id E115B3AD4; Thu, 8 Aug 2019 21:44:37 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x78LiboX029149; Thu, 8 Aug 2019 21:44:37 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x78Lib09029148; Thu, 8 Aug 2019 21:44:37 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201908082144.x78Lib09029148@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Thu, 8 Aug 2019 21:44:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r350792 - stable/11/sys/dev/ahci X-SVN-Group: stable-11 X-SVN-Commit-Author: mav X-SVN-Commit-Paths: stable/11/sys/dev/ahci X-SVN-Commit-Revision: 350792 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 Aug 2019 21:44:38 -0000 Author: mav Date: Thu Aug 8 21:44:37 2019 New Revision: 350792 URL: https://svnweb.freebsd.org/changeset/base/350792 Log: MFC r340092 (by imp): Implement ability to turn on/off PHYs for AHCI devices. As part of Chuck's work on fixing kernel crashes caused by disk I/O errors, it is useful to be able to trigger various kinds of errors. This patch allows causing an AHCI-attached disk to disappear, by having the driver keep the PHY disabled when the driver would otherwise enable the PHY. It also allows making the disk reappear by having the driver go back to setting the PHY enable/disable state as it normal would and simulating the hardware event that causes a bus rescan. Modified: stable/11/sys/dev/ahci/ahci.c stable/11/sys/dev/ahci/ahci.h Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/dev/ahci/ahci.c ============================================================================== --- stable/11/sys/dev/ahci/ahci.c Thu Aug 8 21:43:00 2019 (r350791) +++ stable/11/sys/dev/ahci/ahci.c Thu Aug 8 21:44:37 2019 (r350792) @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -78,6 +79,8 @@ static void ahci_stop(struct ahci_channel *ch); static void ahci_clo(struct ahci_channel *ch); static void ahci_start_fr(struct ahci_channel *ch); static void ahci_stop_fr(struct ahci_channel *ch); +static int ahci_phy_check_events(struct ahci_channel *ch, u_int32_t serr); +static uint32_t ahci_ch_detval(struct ahci_channel *ch, uint32_t val); static int ahci_sata_connect(struct ahci_channel *ch); static int ahci_sata_phy_reset(struct ahci_channel *ch); @@ -98,6 +101,13 @@ static MALLOC_DEFINE(M_AHCI, "AHCI driver", "AHCI driv #define RECOVERY_REQUEST_SENSE 2 #define recovery_slot spriv_field1 +static uint32_t +ahci_ch_detval(struct ahci_channel *ch, uint32_t val) +{ + + return ch->disablephy ? ATA_SC_DET_DISABLE : val; +} + int ahci_ctlr_setup(device_t dev) { @@ -662,11 +672,38 @@ ahci_ch_probe(device_t dev) } static int +ahci_ch_disablephy_proc(SYSCTL_HANDLER_ARGS) +{ + struct ahci_channel *ch; + int error, value; + + ch = arg1; + value = ch->disablephy; + error = sysctl_handle_int(oidp, &value, 0, req); + if (error != 0 || req->newptr == NULL || (value != 0 && value != 1)) + return (error); + + mtx_lock(&ch->mtx); + ch->disablephy = value; + if (value) { + ahci_ch_deinit(ch->dev); + } else { + ahci_ch_init(ch->dev); + ahci_phy_check_events(ch, ATA_SE_PHY_CHANGED | ATA_SE_EXCHANGED); + } + mtx_unlock(&ch->mtx); + + return (0); +} + +static int ahci_ch_attach(device_t dev) { struct ahci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ahci_channel *ch = device_get_softc(dev); struct cam_devq *devq; + struct sysctl_ctx_list *ctx; + struct sysctl_oid *tree; int rid, error, i, sata_rev = 0; u_int32_t version; @@ -784,6 +821,11 @@ ahci_ch_attach(device_t dev) ahci_ch_pm, ch); } mtx_unlock(&ch->mtx); + ctx = device_get_sysctl_ctx(dev); + tree = device_get_sysctl_tree(dev); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "disable_phy", + CTLFLAG_RW | CTLTYPE_UINT, ch, 0, ahci_ch_disablephy_proc, "IU", + "Disable PHY"); return (0); err3: @@ -2494,7 +2536,7 @@ static int ahci_sata_phy_reset(struct ahci_channel *ch) { int sata_rev; - uint32_t val; + uint32_t val, detval; if (ch->listening) { val = ATA_INL(ch->r_mem, AHCI_P_CMD); @@ -2511,12 +2553,14 @@ ahci_sata_phy_reset(struct ahci_channel *ch) val = ATA_SC_SPD_SPEED_GEN3; else val = 0; + detval = ahci_ch_detval(ch, ATA_SC_DET_RESET); ATA_OUTL(ch->r_mem, AHCI_P_SCTL, - ATA_SC_DET_RESET | val | + detval | val | ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER); DELAY(1000); + detval = ahci_ch_detval(ch, ATA_SC_DET_IDLE); ATA_OUTL(ch->r_mem, AHCI_P_SCTL, - ATA_SC_DET_IDLE | val | ((ch->pm_level > 0) ? 0 : + detval | val | ((ch->pm_level > 0) ? 0 : (ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER))); if (!ahci_sata_connect(ch)) { if (ch->caps & AHCI_CAP_SSS) { Modified: stable/11/sys/dev/ahci/ahci.h ============================================================================== --- stable/11/sys/dev/ahci/ahci.h Thu Aug 8 21:43:00 2019 (r350791) +++ stable/11/sys/dev/ahci/ahci.h Thu Aug 8 21:44:37 2019 (r350792) @@ -459,6 +459,8 @@ struct ahci_channel { struct mtx_padalign mtx; /* state lock */ STAILQ_HEAD(, ccb_hdr) doneq; /* queue of completed CCBs */ int batch; /* doneq is in use */ + + int disablephy; /* keep PHY disabled */ }; struct ahci_enclosure {