PCI quirk: RS780/RS880: work around missing MSI initialization
authorClemens Ladisch <clemens@ladisch.de>
Mon, 22 Mar 2010 08:52:16 +0000 (09:52 +0100)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Wed, 24 Mar 2010 20:21:38 +0000 (13:21 -0700)
AMD says in section 2.5.4 (GFX MSI Enable) of #43291 (AMD 780G Family
Register Programming Requirements):

  The SBIOS must enable internal graphics MSI capability in GCCFG by
  setting the following: NBCFG.NB_CNTL.STRAP_MSI_ENABLE='1'

Quite a few BIOS writers misinterpret this sentence and think that
enabling MSI is an optional feature.  However, clearing that bit just
prevents delivery of MSI messages but does not remove the MSI PCI
capabilities registers, and so leaves these devices unusable for any
driver that attempts to use MSI.

Setting that bit is not possible after the BIOS has locked down the
configuration registers, so we have to manually disable MSI for the
affected devices.

This fixes the codec communication errors in the HDA driver when
accessing the HDMI audio device, and allows us to get rid of the
overcautious quirk in radeon_irq_kms.c.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Tested-by: Alex Deucher <alexdeucher@gamil.com>
Cc: <stable@kernel.org>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/pci/quirks.c

index 3cfd60fd00835343f8cacececcb01ba600521133..ea4c645ece115b0fc9fc19146358011ab066a708 100644 (file)
@@ -116,13 +116,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
        }
        /* enable msi */
        rdev->msi_enabled = 0;
-       /* MSIs don't seem to work on my rs780;
-        * not sure about rs880 or other rs780s.
-        * Needs more investigation.
-        */
-       if ((rdev->family >= CHIP_RV380) &&
-           (rdev->family != CHIP_RS780) &&
-           (rdev->family != CHIP_RS880)) {
+       if (rdev->family >= CHIP_RV380) {
                int ret = pci_enable_msi(rdev->pdev);
                if (!ret) {
                        rdev->msi_enabled = 1;
index 8284958fc5305529ed0daabe0076b1faff8ce6e9..bb5b46abc996f527a8688964734ac1e64fd2dd76 100644 (file)
@@ -2493,6 +2493,39 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4374,
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
                        quirk_msi_intx_disable_bug);
 
+/*
+ * MSI does not work with the AMD RS780/RS880 internal graphics and HDMI audio
+ * devices unless the BIOS has initialized the nb_cntl.strap_msi_enable bit.
+ */
+static void __init rs780_int_gfx_disable_msi(struct pci_dev *int_gfx_bridge)
+{
+       u32 nb_cntl;
+
+       if (!int_gfx_bridge->subordinate)
+               return;
+
+       pci_bus_write_config_dword(int_gfx_bridge->bus, PCI_DEVFN(0, 0),
+                                  0x60, 0);
+       pci_bus_read_config_dword(int_gfx_bridge->bus, PCI_DEVFN(0, 0),
+                                 0x64, &nb_cntl);
+
+       if (!(nb_cntl & BIT(10))) {
+               dev_warn(&int_gfx_bridge->dev,
+                        FW_WARN "RS780: MSI for internal graphics disabled\n");
+               int_gfx_bridge->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
+       }
+}
+
+#define PCI_DEVICE_ID_AMD_RS780_P2P_INT_GFX    0x9602
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,
+                       PCI_DEVICE_ID_AMD_RS780_P2P_INT_GFX,
+                       rs780_int_gfx_disable_msi);
+/* wrong vendor ID on M4A785TD motherboard: */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASUSTEK,
+                       PCI_DEVICE_ID_AMD_RS780_P2P_INT_GFX,
+                       rs780_int_gfx_disable_msi);
+
 #endif /* CONFIG_PCI_MSI */
 
 #ifdef CONFIG_PCI_IOV