diff mbox

[Regression,post-rc2] Commit a5ee4eb7541 breaks OpenGL on RS780 (was: Re: Linux 2.6.34-rc3)

Message ID 1270318093.15869.1368145605@webmail.messagingengine.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Clemens Ladisch April 3, 2010, 6:08 p.m. UTC
None
diff mbox

Patch

==========

Subject: PCI quirk: RS780/RS880: work around wrong vendor IDs of RS780 bridge

On many RS780 systems, the vendor ID of the PCI/PCI bridge for the
internal graphics is set to that of the mainboard vendor, so the quirk
would not match and failed to notice the disabled MSI.

Since we do not know in advance all possible vendor IDs, we have to
declare the quirk on another device with an ID that is known to be
correct, and use that as a stepping stone to find the PCI/PCI bridge,
if present.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Cc: <stable@kernel.org>

--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2483,34 +2483,38 @@  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AT
  * 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)
+static void __init rs780_int_gfx_disable_msi(struct pci_dev *host_bridge)
 {
+	struct pci_dev *int_gfx_bridge;
 	u32 nb_cntl;
 
-	if (!int_gfx_bridge->subordinate)
+	/*
+	 * Many OEMs change the vendor ID of the internal graphics PCI/PCI
+	 * bridge, so we use the possible vendor/device IDs of the host bridge
+	 * for the declared quirk, and search for the PCI/PCI bridge by slot
+	 * number.
+	 */
+	int_gfx_bridge = pci_get_slot(host_bridge->bus, PCI_DEVFN(1, 0));
+	if (!int_gfx_bridge)
 		return;
+	if (int_gfx_bridge->device != 0x9602 || !int_gfx_bridge->subordinate)
+		goto out;
 
-	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);
+	pci_write_config_dword(host_bridge, 0x60, 0);
+	pci_read_config_dword(host_bridge, 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
+out:
+	pci_dev_put(int_gfx_bridge);
+}
 
-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);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9600, rs780_int_gfx_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9601, rs780_int_gfx_disable_msi);
 
 #endif /* CONFIG_PCI_MSI */