> 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

Reply via email to