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/52ad94b463e2
branches:  netbsd-9
changeset: 948757:52ad94b463e2
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 9b2e85fdf14c -r 52ad94b463e2 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 9b2e85fdf14c -r 52ad94b463e2 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 9b2e85fdf14c -r 52ad94b463e2 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 9b2e85fdf14c -r 52ad94b463e2 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