On Fri, Jun 24, 2011 at 9:35 PM, Mark Kettenis <[email protected]>
wrote:
>> From: Jonathan Matthew
>> Date: Fri, 24 Jun 2011 16:49:50 +1000
>>
>> > Which shows how badly the chosen name for that function really is.
>> >
>> > I did some digging into the issue.  If you look at 3400 docs, you'll
>> > see that description of the AHCI_REG_CAP registers says that the BIOS
>> > should set the BIOS should set the AHCI_REG_CAP_SPM bit (the port
>> > multiplier capability bit) to 0.  The documented default value for
>> > this register has the bit set to 1 though.  Also, the revision history
>> > mentions the removal of port multiplier functionality.  I guess what's
>> > happened here is that Intel tried to support port multipliers,
>> > discovered that it didn't work properly and told BIOS developers to
>> > disable it.  Unsurprisingly some BIOS developers didn't get the memo
>> > and left the bit in its default state.  So it's obvious that all
>> > 3400/5-Series chipset AHCI variants are affected, and we should apply
>> > the same fix to all of them.
>> >
>> > I looked at other chipsets as well, and the documentation strongly
>> > suggests that the older (ICH) chipsets have the same issue.  The
>> > specified default value has the bit turned on, but the bit is either
>> > undocumented or is documented as "set to 0 by the BIOS".  And even the
>> > new 6-series PCH seems to be affected.  On the other hand Intel still
>> > claims that port multipliers are supported by some of the ICH10
>> > variants.  I'm really curious wether there are any machines where port
>> > multipliers work on the Intel AHCI controller ports.  If not, perhaps
>> > we should blacklist all of the Intel chipsets.
>>
>> The only mentions I can see on Intel's website of port multipliers
>> being supported are on overview pages for 3400 and ICH9, and when you
>> look at the data sheets for those, the revision history says it was
>> removed. For all the other chipsets I looked at, they don't mention it
>> on the overview page and say "port multipliers not supported" in the
>> data sheet. I'm not sure what to make of the default values for the
>> AHCI capabilities register - several of the other bits don't seem to
>> match up with the descriptions, even in cases where they haven't
>> withdrawn support for a feature.
>
> But the default value, and the language describing the SPM bit really
> is very similar across ICH7, ICH8, ICH10, 3400/5-Series and
> C200/6-Series.  For all these chipsets the datasheet says that the
> BIOS should set the bit to 0.  That is no accident.  It is the same
> piece of VHDL (or whatever Intel uses to design the logic) that's
> simply evolving a bit from generation to generation.  But the port
> multiplier functionality stays non-functional.  People have reported
> issues with ICH7, ICH9 and 3400.  So really, all ICH and PCH variants
> are affected and we should quirk them all.

Good point, I agree. Easier to list them all now rather than waiting
for people to report them one by one.

>> > Arguably, the chosen fix (the AHCI_F_IPMS_PROBE quirk) isn't quite
>> > right.  It is clear that (some) Intel AHCI variants simply don't
>> > support port multipliers, so we should just skip the probe.  On the
>> > other hand, as long as this quirk works, we don't need to introduce
>> > another one.
>>
>> The quirk was introduced for ATI SB600 and SB700 AHCIs where port
>> multipliers do actually work, so I don't really like using it to fix
>> devices where they don't. I just didn't realise that's what I was
>> doing until now.
>
> Hmm, well, the SB600 databook says that port multipliers are supported
> on ASIC revision A13 and above.  So I wonder if the workaround is only
> necessary for the older revisions whithout port multiplier support.

I'll have to check this on Monday when I can get at the machine, but
I'm pretty sure I've had a port multiplier working on an SB600 that
required this quirk.

untested diff follows.

Index: ahci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/ahci.c,v
retrieving revision 1.180
diff -u -r1.180 ahci.c
--- ahci.c      14 Jun 2011 10:40:14 -0000      1.180
+++ ahci.c      24 Jun 2011 12:43:53 -0000
@@ -418,6 +418,7 @@
 #define AHCI_F_NO_NCQ                  (1<<0)
 #define AHCI_F_IGN_FR                  (1<<1)
 #define AHCI_F_IPMS_PROBE              (1<<2)  /* IPMS on failed PMP probe
*/
+#define AHCI_F_NO_PMP                  (1<<3)  /* ignore PMP capability */

        u_int                   sc_ncmds;

@@ -456,7 +457,7 @@
                            struct pci_attach_args *);
 int                    ahci_amd_hudson2_attach(struct ahci_softc *,
                            struct pci_attach_args *);
-int                    ahci_intel_3400_1_attach(struct ahci_softc *,
+int                    ahci_intel_attach(struct ahci_softc *,
                            struct pci_attach_args *);
 int                    ahci_nvidia_mcp_attach(struct ahci_softc *,
                            struct pci_attach_args *);
@@ -480,8 +481,42 @@
        { PCI_VENDOR_ATI,       PCI_PRODUCT_ATI_SBX00_SATA_6,
            NULL,               ahci_ati_sb700_attach },

+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_6SERIES_AHCI_1,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_6SERIES_AHCI_2,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_6321ESB_AHCI,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801GR_AHCI,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801GBM_AHCI,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801H_AHCI_6P,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801H_AHCI_4P,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801HBM_AHCI,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801I_AHCI_1,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801I_AHCI_2,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801I_AHCI_3,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801JD_AHCI,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801JI_AHCI,
+           NULL,               ahci_intel_attach },
        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_3400_AHCI_1,
-           NULL,               ahci_intel_3400_1_attach },
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_3400_AHCI_2,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_3400_AHCI_3,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_3400_AHCI_4,
+           NULL,               ahci_intel_attach },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_EP80579_AHCI,
+           NULL,               ahci_intel_attach },

        { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_MCP65_AHCI_2,
            NULL,               ahci_nvidia_mcp_attach },
@@ -716,9 +751,9 @@
 }

 int
-ahci_intel_3400_1_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
+ahci_intel_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
 {
-       sc->sc_flags |= AHCI_F_IPMS_PROBE;
+       sc->sc_flags |= AHCI_F_NO_PMP;
        return (0);
 }

@@ -2089,6 +2124,7 @@
        }

        if (pmp == 0 ||
+           (ap->ap_sc->sc_flags & AHCI_F_NO_PMP) ||
            !ISSET(ahci_read(ap->ap_sc, AHCI_REG_CAP), AHCI_REG_CAP_SPM)) {
                goto err;
        }

Reply via email to