> Date: Sun, 29 May 2011 23:54:30 +0200 (CEST)
> From: Mark Kettenis <[email protected]>
>
> I'm starting to get some confidence in the new MSI code, so it's
> probably time to enable it. Here is my proposed diff to do so on
> i386. I'm working on a similar, but much simpler diff for amd64. The
> idea is to enable MSI for the most important chipsets from vendors
> that deliver products that are reasonably well documented and aren't
> riddled with nasty bugs. Not sure NVIDIA belongs in that list, but
> one of the machines I'm testing stuff on has an NVIDIA chipset, so
> that's why it is included here. If our favourite chipset didn't make
> the cut, feel free to work with me to add support for it.
>
> Does this look reasonable to people?
>
> To test, you'll need to apply my "MSI on HyperTransport" diff as well
> *which is probably going into the tree tomorrow).
>
> I'll probably commit this somewhere next week, so oks are welcome.
>
Better diff:
Index: pci_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/pci/pci_machdep.c,v
retrieving revision 1.61
diff -u -p -r1.61 pci_machdep.c
--- pci_machdep.c 29 May 2011 10:47:42 -0000 1.61
+++ pci_machdep.c 29 May 2011 22:19:04 -0000
@@ -195,6 +195,9 @@ void
pci_attach_hook(struct device *parent, struct device *self,
struct pcibus_attach_args *pba)
{
+ pci_chipset_tag_t pc = pba->pba_pc;
+ pcitag_t tag;
+ pcireg_t id, class;
#if NBIOS > 0
if (pba->pba_bus == 0)
@@ -204,6 +207,108 @@ pci_attach_hook(struct device *parent, s
if (pba->pba_bus == 0)
printf(": configuration mode %d", pci_mode);
#endif
+
+ if (pba->pba_bus != 0)
+ return;
+
+ /*
+ * In order to decide wether the system supports MSI we look
+ * at the host bridge, which should be device 0 function 0 on
+ * bus 0. It is better to not enable MSI on systems that
+ * support it than the other way around, so be conservative
+ * here. So we don't enable MSI of we don't find a host
+ * bridge there. We also deliberately don't enable MSI on
+ * chipsets from low-end manifacturers like VIA and SiS.
+ */
+ tag = pci_make_tag(pc, 0, 0, 0);
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
+ class = pci_conf_read(pc, tag, PCI_CLASS_REG);
+
+ if (PCI_CLASS(class) != PCI_CLASS_BRIDGE ||
+ PCI_SUBCLASS(class) != PCI_SUBCLASS_BRIDGE_HOST)
+ return;
+
+ switch (PCI_VENDOR(id)) {
+ case PCI_VENDOR_INTEL:
+ /*
+ * For Intel platforms, MSI support was introduced
+ * with the new Pentium 4 processor interrupt delivery
+ * mechanism, so we blacklist all PCI chipsets that
+ * support Pentium III and earlier CPUs.
+ */
+ switch (PCI_PRODUCT(id)) {
+ case PCI_PRODUCT_INTEL_PCMC: /* 82434LX/NX */
+ case PCI_PRODUCT_INTEL_82437FX:
+ case PCI_PRODUCT_INTEL_82437MX:
+ case PCI_PRODUCT_INTEL_82437VX:
+ case PCI_PRODUCT_INTEL_82439HX:
+ case PCI_PRODUCT_INTEL_82439TX:
+ case PCI_PRODUCT_INTEL_82440BX:
+ case PCI_PRODUCT_INTEL_82440BX_AGP:
+ case PCI_PRODUCT_INTEL_82440MX_HB:
+ case PCI_PRODUCT_INTEL_82441FX:
+ case PCI_PRODUCT_INTEL_82443BX:
+ case PCI_PRODUCT_INTEL_82443BX_AGP:
+ case PCI_PRODUCT_INTEL_82443BX_NOAGP:
+ case PCI_PRODUCT_INTEL_82443GX:
+ case PCI_PRODUCT_INTEL_82443LX:
+ case PCI_PRODUCT_INTEL_82443LX_AGP:
+ case PCI_PRODUCT_INTEL_82810_HB:
+ case PCI_PRODUCT_INTEL_82810E_HB:
+ case PCI_PRODUCT_INTEL_82815_HB:
+ case PCI_PRODUCT_INTEL_82820_HB:
+ case PCI_PRODUCT_INTEL_82830M_HB:
+ case PCI_PRODUCT_INTEL_82840_HB:
+ break;
+ default:
+ pba->pba_flags |= PCI_FLAGS_MSI_ENABLED;
+ break;
+ }
+ break;
+ case PCI_VENDOR_NVIDIA:
+ /*
+ * Since NVIDIA chipsets are completely undocumented,
+ * we have to make a guess here. We assume that all
+ * chipsets that support PCIe include support for MSI,
+ * since support for MSI is mandated by the PCIe
+ * standard.
+ */
+ switch (PCI_PRODUCT(id)) {
+ case PCI_PRODUCT_NVIDIA_NFORCE_PCHB:
+ case PCI_PRODUCT_NVIDIA_NFORCE2_PCHB:
+ break;
+ default:
+ pba->pba_flags |= PCI_FLAGS_MSI_ENABLED;
+ break;
+ }
+ break;
+ case PCI_VENDOR_AMD:
+ /*
+ * The AMD-750 and AMD-760 chipsets don't support MSI.
+ */
+ switch (PCI_PRODUCT(id)) {
+ case PCI_PRODUCT_AMD_SC751_SC:
+ case PCI_PRODUCT_AMD_761_PCHB:
+ case PCI_PRODUCT_AMD_762_PCHB:
+ break;
+ default:
+ pba->pba_flags |= PCI_FLAGS_MSI_ENABLED;
+ break;
+ }
+ break;
+ }
+
+ /*
+ * Don't enable MSI on a HyperTransport bus. In order to
+ * determine that bus 0 is a HyperTransport bus, we look at
+ * device 24 function 0, which is the HyperTransport
+ * host/primary interface integrated on most 64-bit AMD CPUs.
+ * If that device has a HyperTransport capability, bus 0 must
+ * be a HyperTransport bus and we disable MSI.
+ */
+ tag = pci_make_tag(pc, 0, 24, 0);
+ if (pci_get_capability(pc, tag, PCI_CAP_HT, NULL, NULL))
+ pba->pba_flags &= ~PCI_FLAGS_MSI_ENABLED;
}
int