aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-03-22 04:52:16 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-03-24 16:21:38 -0400
commita5ee4eb75413c145334c30e43f1af9875dad6fd7 (patch)
tree721f45ddafb0934dcd445de47bea9c1d0ad3efe2
parentca8463926306580c25e62eb901a206530d480cae (diff)
PCI quirk: RS780/RS880: work around missing MSI initialization
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>
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq_kms.c8
-rw-r--r--drivers/pci/quirks.c33
2 files changed, 34 insertions, 7 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 3cfd60fd0083..ea4c645ece11 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -116,13 +116,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
116 } 116 }
117 /* enable msi */ 117 /* enable msi */
118 rdev->msi_enabled = 0; 118 rdev->msi_enabled = 0;
119 /* MSIs don't seem to work on my rs780; 119 if (rdev->family >= CHIP_RV380) {
120 * not sure about rs880 or other rs780s.
121 * Needs more investigation.
122 */
123 if ((rdev->family >= CHIP_RV380) &&
124 (rdev->family != CHIP_RS780) &&
125 (rdev->family != CHIP_RS880)) {
126 int ret = pci_enable_msi(rdev->pdev); 120 int ret = pci_enable_msi(rdev->pdev);
127 if (!ret) { 121 if (!ret) {
128 rdev->msi_enabled = 1; 122 rdev->msi_enabled = 1;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 8284958fc530..bb5b46abc996 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2493,6 +2493,39 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4374,
2493DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375, 2493DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
2494 quirk_msi_intx_disable_bug); 2494 quirk_msi_intx_disable_bug);
2495 2495
2496/*
2497 * MSI does not work with the AMD RS780/RS880 internal graphics and HDMI audio
2498 * devices unless the BIOS has initialized the nb_cntl.strap_msi_enable bit.
2499 */
2500static void __init rs780_int_gfx_disable_msi(struct pci_dev *int_gfx_bridge)
2501{
2502 u32 nb_cntl;
2503
2504 if (!int_gfx_bridge->subordinate)
2505 return;
2506
2507 pci_bus_write_config_dword(int_gfx_bridge->bus, PCI_DEVFN(0, 0),
2508 0x60, 0);
2509 pci_bus_read_config_dword(int_gfx_bridge->bus, PCI_DEVFN(0, 0),
2510 0x64, &nb_cntl);
2511
2512 if (!(nb_cntl & BIT(10))) {
2513 dev_warn(&int_gfx_bridge->dev,
2514 FW_WARN "RS780: MSI for internal graphics disabled\n");
2515 int_gfx_bridge->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
2516 }
2517}
2518
2519#define PCI_DEVICE_ID_AMD_RS780_P2P_INT_GFX 0x9602
2520
2521DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,
2522 PCI_DEVICE_ID_AMD_RS780_P2P_INT_GFX,
2523 rs780_int_gfx_disable_msi);
2524/* wrong vendor ID on M4A785TD motherboard: */
2525DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASUSTEK,
2526 PCI_DEVICE_ID_AMD_RS780_P2P_INT_GFX,
2527 rs780_int_gfx_disable_msi);
2528
2496#endif /* CONFIG_PCI_MSI */ 2529#endif /* CONFIG_PCI_MSI */
2497 2530
2498#ifdef CONFIG_PCI_IOV 2531#ifdef CONFIG_PCI_IOV