Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-9]: src/sys/dev/ic Pull up following revision(s) (requested by jm...
details: https://anonhg.NetBSD.org/src/rev/04c6ef803b8c
branches: netbsd-9
changeset: 964244:04c6ef803b8c
user: martin <martin%NetBSD.org@localhost>
date: Wed Dec 30 15:12:38 2020 +0000
description:
Pull up following revision(s) (requested by jmcneill in ticket #1167):
sys/dev/ic/ahcisata_core.c: revision 1.84
sys/dev/ic/ahcisata_core.c: revision 1.85
sys/dev/ic/ahcisata_core.c: revision 1.88
sys/dev/ic/ahcisata_core.c: revision 1.89
sys/arch/arm/nvidia/tegra_ahcisata.c: revision 1.13
sys/dev/ic/ahcisatavar.h: revision 1.26
sys/dev/ic/ahcisata_core.c: revision 1.90
sys/dev/ic/ahcisata_core.c: revision 1.91
sys/dev/ic/ahcisata_core.c: revision 1.92
sys/dev/ata/satareg.h: revision 1.6
ahci_exec_fis: wait for the correct amount of time when AT_WAIT is set
Retry clearing WDCTL_RST a few times before giving up. Makes SATA work in
Solidrun Honeycomb LX2K.
AHCI 1.3.1 specification says that it is good practice for system software
to 'zero-out' the memory allocated and referenced by PxCLB and PxFB.
ahci_intr: use ffs in the port bitmask instead of looping over all 32 bits
AHCI 1.3.1 section 5.5.3 "Processing Completed Commands" says that we
should clear PxIS before IS.IPS.
Add G3 and DevSleep definitions. This changes the mask used by
SControl_IPM_NONE from 0x3 to 0x7.
Make sure to ack IS after PxIS when polling and when using multiple MSI-X
messages.
Remove the AHCI_QUIRK_SKIP_RESET quirk now that the underlying issue is
fixed.
diffstat:
sys/arch/arm/nvidia/tegra_ahcisata.c | 5 +-
sys/dev/ata/satareg.h | 8 ++-
sys/dev/ic/ahcisata_core.c | 96 +++++++++++++++++++++++------------
sys/dev/ic/ahcisatavar.h | 5 +-
4 files changed, 72 insertions(+), 42 deletions(-)
diffs (280 lines):
diff -r 864ce4222894 -r 04c6ef803b8c sys/arch/arm/nvidia/tegra_ahcisata.c
--- a/sys/arch/arm/nvidia/tegra_ahcisata.c Mon Dec 28 20:24:05 2020 +0000
+++ b/sys/arch/arm/nvidia/tegra_ahcisata.c Wed Dec 30 15:12:38 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_ahcisata.c,v 1.12 2018/12/14 12:29:22 skrll Exp $ */
+/* $NetBSD: tegra_ahcisata.c,v 1.12.4.1 2020/12/30 15:12:38 martin Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_ahcisata.c,v 1.12 2018/12/14 12:29:22 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_ahcisata.c,v 1.12.4.1 2020/12/30 15:12:38 martin Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -202,7 +202,6 @@
aprint_error(": couldn't map ahci registers: %d\n", error);
return;
}
- sc->sc.sc_ahci_quirks = AHCI_QUIRK_SKIP_RESET;
aprint_naive("\n");
aprint_normal(": SATA\n");
diff -r 864ce4222894 -r 04c6ef803b8c sys/dev/ata/satareg.h
--- a/sys/dev/ata/satareg.h Mon Dec 28 20:24:05 2020 +0000
+++ b/sys/dev/ata/satareg.h Wed Dec 30 15:12:38 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: satareg.h,v 1.5 2008/04/28 20:23:47 martin Exp $ */
+/* $NetBSD: satareg.h,v 1.5.94.1 2020/12/30 15:12:38 martin Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -65,6 +65,7 @@
#define SStatus_SPD_NONE (0x0 << 4) /* no negotiated speed */
#define SStatus_SPD_G1 (0x1 << 4) /* Generation 1 (1.5Gb/s) */
#define SStatus_SPD_G2 (0x2 << 4) /* Generation 2 (3.0Gb/s) */
+#define SStatus_SPD_G3 (0x3 << 4) /* Generation 3 (6.0Gb/s) */
#define SStatus_SPD_mask (0xf << 4)
#define SStatus_SPD_shift 4
/*
@@ -75,6 +76,7 @@
#define SStatus_IPM_ACTIVE (0x1 << 8) /* ACTIVE state */
#define SStatus_IPM_PARTIAL (0x2 << 8) /* PARTIAL pm state */
#define SStatus_IPM_SLUMBER (0x6 << 8) /* SLUMBER pm state */
+#define SStatus_IPM_DEVSLEEP (0x8 << 8) /* DevSleep pm state */
#define SStatus_IPM_mask (0xf << 8)
#define SStatus_IPM_shift 8
@@ -130,6 +132,7 @@
#define SControl_SPD_ANY (0x0 << 4) /* No restrictions */
#define SControl_SPD_G1 (0x1 << 4) /* Generation 1 (1.5Gb/s) */
#define SControl_SPD_G2 (0x2 << 4) /* Generation 2 (3.0Gb/s) */
+#define SControl_SPD_G3 (0x3 << 4) /* Generation 3 (6.0Gb/s) */
/*
* The IPM field represents the enabled interface power management
* states that can be invoked via the Serial ATA interface power
@@ -138,7 +141,8 @@
#define SControl_IPM_ANY (0x0 << 8) /* No restrictions */
#define SControl_IPM_NOPARTIAL (0x1 << 8) /* PARTIAL disabled */
#define SControl_IPM_NOSLUMBER (0x2 << 8) /* SLUMBER disabled */
-#define SControl_IPM_NONE (0x3 << 8) /* No power management */
+#define SControl_IPM_NODEVSLEEP (0x4 << 8) /* DevSleep disabled */
+#define SControl_IPM_NONE (0x7 << 8) /* No power management */
/*
* The SPM field selects a power management state. A non-zero
* value written to this field causes initiation of the selected
diff -r 864ce4222894 -r 04c6ef803b8c sys/dev/ic/ahcisata_core.c
--- a/sys/dev/ic/ahcisata_core.c Mon Dec 28 20:24:05 2020 +0000
+++ b/sys/dev/ic/ahcisata_core.c Wed Dec 30 15:12:38 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisata_core.c,v 1.75.4.3 2020/01/21 15:19:51 martin Exp $ */
+/* $NetBSD: ahcisata_core.c,v 1.75.4.4 2020/12/30 15:12:38 martin Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.75.4.3 2020/01/21 15:19:51 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.75.4.4 2020/12/30 15:12:38 martin Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -84,6 +84,7 @@
int, int);
static void ahci_channel_recover(struct ata_channel *, int, uint32_t);
static int ahci_dma_setup(struct ata_channel *, int, void *, size_t, int);
+static int ahci_intr_port_common(struct ata_channel *);
#if NATAPIBUS > 0
static void ahci_atapibus_attach(struct atabus_softc *);
@@ -363,6 +364,9 @@
return;
}
sc->sc_cmd_hdr = cmdhp;
+ memset(cmdhp, 0, dmasize);
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_hdrd, 0, dmasize,
+ BUS_DMASYNC_PREWRITE);
ahci_enable_intrs(sc);
@@ -429,6 +433,9 @@
", error=%d\n", AHCINAME(sc), error);
break;
}
+ memset(cmdtblp, 0, dmasize);
+ bus_dmamap_sync(sc->sc_dmat, achp->ahcic_cmd_tbld, 0,
+ dmasize, BUS_DMASYNC_PREWRITE);
achp->ahcic_cmdh = (struct ahci_cmd_header *)
((char *)cmdhp + AHCI_CMDH_SIZE * port);
achp->ahcic_bus_cmdh = sc->sc_cmd_hdrd->dm_segs[0].ds_addr +
@@ -586,17 +593,20 @@
ahci_intr(void *v)
{
struct ahci_softc *sc = v;
- uint32_t is;
- int i, r = 0;
+ uint32_t is, ports;
+ int bit, r = 0;
while ((is = AHCI_READ(sc, AHCI_IS))) {
AHCIDEBUG_PRINT(("%s ahci_intr 0x%x\n", AHCINAME(sc), is),
DEBUG_INTR);
r = 1;
+ ports = is;
+ while ((bit = ffs(ports)) != 0) {
+ bit--;
+ ahci_intr_port_common(&sc->sc_channels[bit].ata_channel);
+ ports &= ~(1U << bit);
+ }
AHCI_WRITE(sc, AHCI_IS, is);
- for (i = 0; i < AHCI_MAX_PORTS; i++)
- if (is & (1U << i))
- ahci_intr_port(&sc->sc_channels[i]);
}
return r;
@@ -608,6 +618,20 @@
struct ahci_channel *achp = v;
struct ata_channel *chp = &achp->ata_channel;
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
+ int ret;
+
+ ret = ahci_intr_port_common(chp);
+ if (ret) {
+ AHCI_WRITE(sc, AHCI_IS, 1U << chp->ch_channel);
+ }
+
+ return ret;
+}
+
+static int
+ahci_intr_port_common(struct ata_channel *chp)
+{
+ struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
uint32_t is, tfd, sact;
struct ata_xfer *xfer;
int slot = -1;
@@ -617,8 +641,8 @@
is = AHCI_READ(sc, AHCI_P_IS(chp->ch_channel));
AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), is);
- AHCIDEBUG_PRINT((
- "ahci_intr_port %s port %d is 0x%x CI 0x%x SACT 0x%x TFD 0x%x\n",
+ AHCIDEBUG_PRINT(("ahci_intr_port_common %s port %d "
+ "is 0x%x CI 0x%x SACT 0x%x TFD 0x%x\n",
AHCINAME(sc),
chp->ch_channel, is,
AHCI_READ(sc, AHCI_P_CI(chp->ch_channel)),
@@ -761,14 +785,10 @@
uint32_t is;
/*
- * Base timeout is specified in ms.
- * If we are allowed to sleep, wait a tick each round.
- * Otherwise delay for 10ms on each round.
+ * Base timeout is specified in ms. Delay for 10ms
+ * on each round.
*/
- if (flags & AT_WAIT)
- timeout = MAX(1, mstohz(timeout));
- else
- timeout = timeout / 10;
+ timeout = timeout / 10;
AHCI_CMDH_SYNC(sc, achp, slot,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -813,7 +833,7 @@
struct ahci_cmd_header *cmd_h;
int i, error = 0;
uint32_t sig, cmd;
- int noclo_retry = 0;
+ int noclo_retry = 0, retry;
ata_channel_lock_owned(chp);
@@ -851,9 +871,6 @@
KASSERT(sc->sc_ahci_cap & AHCI_CAP_SPM);
}
- if (sc->sc_ahci_quirks & AHCI_QUIRK_SKIP_RESET)
- goto skip_reset;
-
/* polled command, assume interrupts are disabled */
cmd_h = &achp->ahcic_cmdh[c_slot];
@@ -895,25 +912,36 @@
*/
ata_delay(chp, 10, "ahcirstw", flags);
- cmd_h->cmdh_flags = htole16(RHD_FISLEN / 4 |
- (drive << AHCI_CMDH_F_PMP_SHIFT));
- cmd_h->cmdh_prdbc = 0;
- memset(cmd_tbl->cmdt_cfis, 0, 64);
- cmd_tbl->cmdt_cfis[fis_type] = RHD_FISTYPE;
- cmd_tbl->cmdt_cfis[rhd_c] = drive;
- cmd_tbl->cmdt_cfis[rhd_control] = WDCTL_4BIT;
- switch (ahci_exec_fis(chp, 310, flags, c_slot)) {
- case ERR_DF:
- case TIMEOUT:
+ /*
+ * Try to clear WDCTL_RST a few times before giving up.
+ */
+ for (error = EBUSY, retry = 0; error != 0 && retry < 5; retry++) {
+ cmd_h->cmdh_flags = htole16(RHD_FISLEN / 4 |
+ (drive << AHCI_CMDH_F_PMP_SHIFT));
+ cmd_h->cmdh_prdbc = 0;
+ memset(cmd_tbl->cmdt_cfis, 0, 64);
+ cmd_tbl->cmdt_cfis[fis_type] = RHD_FISTYPE;
+ cmd_tbl->cmdt_cfis[rhd_c] = drive;
+ cmd_tbl->cmdt_cfis[rhd_control] = WDCTL_4BIT;
+ switch (ahci_exec_fis(chp, 310, flags, c_slot)) {
+ case ERR_DF:
+ case TIMEOUT:
+ error = EBUSY;
+ break;
+ default:
+ error = 0;
+ break;
+ }
+ if (error == 0) {
+ break;
+ }
+ }
+ if (error == EBUSY) {
aprint_error("%s port %d: clearing WDCTL_RST failed "
"for drive %d\n", AHCINAME(sc), chp->ch_channel, drive);
- error = EBUSY;
goto end;
- default:
- break;
}
-skip_reset:
/*
* wait 31s for BSY to clear
* This should not be needed, but some controllers clear the
diff -r 864ce4222894 -r 04c6ef803b8c sys/dev/ic/ahcisatavar.h
--- a/sys/dev/ic/ahcisatavar.h Mon Dec 28 20:24:05 2020 +0000
+++ b/sys/dev/ic/ahcisatavar.h Wed Dec 30 15:12:38 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisatavar.h,v 1.22.4.1 2020/01/21 15:19:51 martin Exp $ */
+/* $NetBSD: ahcisatavar.h,v 1.22.4.2 2020/12/30 15:12:38 martin Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -58,8 +58,7 @@
#define AHCI_PCI_QUIRK_FORCE __BIT(0) /* force attach */
#define AHCI_PCI_QUIRK_BAD64 __BIT(1) /* broken 64-bit DMA */
#define AHCI_QUIRK_BADPMP __BIT(2) /* broken PMP support, ignore */
-#define AHCI_QUIRK_SKIP_RESET __BIT(4) /* skip drive reset sequence */
-#define AHCI_QUIRK_BADNCQ __BIT(5) /* possibly broken NCQ support, ignore */
+#define AHCI_QUIRK_BADNCQ __BIT(3) /* possibly broken NCQ support, ignore */
uint32_t sc_ahci_cap; /* copy of AHCI_CAP */
int sc_ncmds; /* number of command slots */
Home |
Main Index |
Thread Index |
Old Index