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