Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Work around some SATA PMP issues in some AHCI contro...



details:   https://anonhg.NetBSD.org/src/rev/74d860d0b957
branches:  trunk
changeset: 780898:74d860d0b957
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Fri Aug 10 16:35:00 2012 +0000

description:
Work around some SATA PMP issues in some AHCI controllers by either
disabling PMP entirely, or special handling in the reset function.
Controller list from linux and FreeBSD.

diffstat:

 sys/dev/ic/ahcisata_core.c |   20 ++++-
 sys/dev/ic/ahcisatavar.h   |    7 +-
 sys/dev/pci/ahcisata_pci.c |  164 ++++++++++++++++++++++++++++++++++----------
 3 files changed, 151 insertions(+), 40 deletions(-)

diffs (truncated from 324 to 300 lines):

diff -r 4e763c8db7a1 -r 74d860d0b957 sys/dev/ic/ahcisata_core.c
--- a/sys/dev/ic/ahcisata_core.c        Fri Aug 10 16:34:23 2012 +0000
+++ b/sys/dev/ic/ahcisata_core.c        Fri Aug 10 16:35:00 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ahcisata_core.c,v 1.40 2012/07/31 15:50:34 bouyer Exp $        */
+/*     $NetBSD: ahcisata_core.c,v 1.41 2012/08/10 16:35:00 bouyer Exp $        */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.40 2012/07/31 15:50:34 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.41 2012/08/10 16:35:00 bouyer Exp $");
 
 #include <sys/types.h>
 #include <sys/malloc.h>
@@ -225,6 +225,11 @@
                return;
 
        sc->sc_ahci_cap = AHCI_READ(sc, AHCI_CAP);
+       if (sc->sc_achi_quirks & AHCI_QUIRK_BADPMP) {
+               aprint_verbose_dev(sc->sc_atac.atac_dev,
+                   "ignoring broken port multiplier support\n");
+               sc->sc_ahci_cap &= ~AHCI_CAP_SPM;
+       }
        sc->sc_atac.atac_nchannels = (sc->sc_ahci_cap & AHCI_CAP_NPMASK) + 1;
        sc->sc_ncmds = ((sc->sc_ahci_cap & AHCI_CAP_NCS) >> 8) + 1;
        ahci_rev = AHCI_READ(sc, AHCI_VS);
@@ -655,6 +660,7 @@
        if (drive > 0) {
                KASSERT(sc->sc_ahci_cap & AHCI_CAP_SPM);
        }
+again:
        /* polled command, assume interrupts are disabled */
        /* use slot 0 to send reset, the channel is idle */
        cmd_h = &achp->ahcic_cmdh[0];
@@ -687,6 +693,16 @@
        switch(ahci_exec_fis(chp, 31, flags)) {
        case ERR_DF:
        case TIMEOUT:
+               if ((sc->sc_achi_quirks & AHCI_QUIRK_BADPMPRESET) != 0 &&
+                   drive == PMP_PORT_CTL) {
+                       /*
+                        * some controllers fails to reset when
+                        * targeting a PMP but a single drive is attached.
+                        * try again with port 0
+                        */
+                       drive = 0;
+                       goto again;
+               }
                aprint_error("%s channel %d: clearing WDCTL_RST failed "
                    "for drive %d\n", AHCINAME(sc), chp->ch_channel, drive);
                if (sigp)
diff -r 4e763c8db7a1 -r 74d860d0b957 sys/dev/ic/ahcisatavar.h
--- a/sys/dev/ic/ahcisatavar.h  Fri Aug 10 16:34:23 2012 +0000
+++ b/sys/dev/ic/ahcisatavar.h  Fri Aug 10 16:35:00 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ahcisatavar.h,v 1.10 2012/07/31 15:50:34 bouyer Exp $  */
+/*     $NetBSD: ahcisatavar.h,v 1.11 2012/08/10 16:35:00 bouyer Exp $  */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -54,6 +54,11 @@
        bus_dma_segment_t sc_cmd_hdr_seg;
        int sc_cmd_hdr_nseg;
        int sc_atac_capflags;
+       int sc_achi_quirks;
+#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_BADPMPRESET __BIT(2)  /* broken PMP support for reset */
 
        int32_t sc_ahci_cap;    /* copy of AHCI_CAP */
        int sc_ncmds; /* number of command slots */
diff -r 4e763c8db7a1 -r 74d860d0b957 sys/dev/pci/ahcisata_pci.c
--- a/sys/dev/pci/ahcisata_pci.c        Fri Aug 10 16:34:23 2012 +0000
+++ b/sys/dev/pci/ahcisata_pci.c        Fri Aug 10 16:35:00 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ahcisata_pci.c,v 1.27 2012/01/30 19:41:18 drochner Exp $       */
+/*     $NetBSD: ahcisata_pci.c,v 1.28 2012/08/10 16:35:00 bouyer Exp $ */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.27 2012/01/30 19:41:18 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.28 2012/08/10 16:35:00 bouyer Exp $");
 
 #include <sys/types.h>
 #include <sys/malloc.h>
@@ -45,58 +45,147 @@
 struct ahci_pci_quirk { 
        pci_vendor_id_t  vendor;        /* Vendor ID */
        pci_product_id_t product;       /* Product ID */
-       int              quirks;        /* quirks; see below */
+       int              quirks;        /* quirks; same as sc_achi_quirks */
 };
 
-#define AHCI_PCI_QUIRK_FORCE   __BIT(0)        /* force attach */
-#define AHCI_PCI_QUIRK_BAD64   __BIT(1)        /* broken 64-bit DMA */
-
 static const struct ahci_pci_quirk ahci_pci_quirks[] = {
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_SATA,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_SATA2,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_SATA3,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_SATA4,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_AHCI_1,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_AHCI_2,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_AHCI_3,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_AHCI_4,
+           AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_SATA,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_SATA2,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_SATA3,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_SATA4,
+            AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_1,
+            AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_2,
+            AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_3,
+            AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_4,
+            AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_5,
+            AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_6,
+            AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_7,
+            AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_AHCI_8,
+            AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_1,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_2,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_3,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_4,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_5,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_6,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_7,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_8,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_9,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_10,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_11,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_AHCI_12,
+           AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_1,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_2,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_3,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_4,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_5,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_6,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_7,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_8,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_9,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_10,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_11,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_AHCI_12,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_1,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_2,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_3,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_4,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_5,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_6,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_7,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_8,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_9,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_10,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_11,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_AHCI_12,
+           AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5288,
            AHCI_PCI_QUIRK_FORCE },
        { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_88SE6121,
-           AHCI_PCI_QUIRK_FORCE },
+           AHCI_PCI_QUIRK_FORCE | AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_88SE6145,
+           AHCI_QUIRK_BADPMP },
        { PCI_VENDOR_MARVELL2, PCI_PRODUCT_MARVELL2_88SE9128,
            AHCI_PCI_QUIRK_FORCE },
        /* ATI SB600 AHCI 64-bit DMA only works on some boards/BIOSes */
        { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB600_SATA_1,
-           AHCI_PCI_QUIRK_BAD64 },
+           AHCI_PCI_QUIRK_BAD64 | AHCI_QUIRK_BADPMPRESET },
+       { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB700_SATA_AHCI,
+           AHCI_QUIRK_BADPMPRESET },
+       { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB700_SATA_RAID,
+           AHCI_QUIRK_BADPMPRESET },
+       { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB700_SATA_RAID5,
+           AHCI_QUIRK_BADPMPRESET },
+       { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB700_SATA_FC,
+           AHCI_QUIRK_BADPMPRESET },
+       { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB700_SATA_AHCI2,
+           AHCI_QUIRK_BADPMPRESET },
+       { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8237R_SATA,
+           AHCI_QUIRK_BADPMP },
+       { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8251_SATA,
+           AHCI_QUIRK_BADPMP },
 };
 
 struct ahci_pci_softc {
@@ -106,7 +195,7 @@
        void * sc_ih;
 };
 
-static bool ahci_pci_has_quirk(pci_vendor_id_t, pci_product_id_t, int);
+static int  ahci_pci_has_quirk(pci_vendor_id_t, pci_product_id_t);
 static int  ahci_pci_match(device_t, cfdata_t, void *);
 static void ahci_pci_attach(device_t, device_t, void *);
 static int  ahci_pci_detach(device_t, int);
@@ -116,16 +205,16 @@
 CFATTACH_DECL_NEW(ahcisata_pci, sizeof(struct ahci_pci_softc),
     ahci_pci_match, ahci_pci_attach, ahci_pci_detach, NULL);
 
-static bool
-ahci_pci_has_quirk(pci_vendor_id_t vendor, pci_product_id_t product, int quirk)
+static int
+ahci_pci_has_quirk(pci_vendor_id_t vendor, pci_product_id_t product)
 {
        int i;
 
        for (i = 0; i < __arraycount(ahci_pci_quirks); i++)
                if (vendor == ahci_pci_quirks[i].vendor &&
                    product == ahci_pci_quirks[i].product)
-                       return (ahci_pci_quirks[i].quirks & quirk) != 0;
-       return false;
+                       return ahci_pci_quirks[i].quirks;
+       return 0;
 }
 
 static int
@@ -138,9 +227,8 @@
        int ret = 0;
        bool force;
 



Home | Main Index | Thread Index | Old Index