Merge branch 'pci/printk'
[linux-2.6-microblaze.git] / drivers / pci / quirks.c
index a59ad09..b9489b3 100644 (file)
@@ -159,8 +159,7 @@ static int __init pci_apply_final_quirks(void)
        u8 tmp;
 
        if (pci_cache_line_size)
-               printk(KERN_DEBUG "PCI: CLS %u bytes\n",
-                      pci_cache_line_size << 2);
+               pr_info("PCI: CLS %u bytes\n", pci_cache_line_size << 2);
 
        pci_apply_fixup_final_quirks = true;
        for_each_pci_dev(dev) {
@@ -177,16 +176,16 @@ static int __init pci_apply_final_quirks(void)
                        if (!tmp || cls == tmp)
                                continue;
 
-                       printk(KERN_DEBUG "PCI: CLS mismatch (%u != %u), using %u bytes\n",
-                              cls << 2, tmp << 2,
-                              pci_dfl_cache_line_size << 2);
+                       pci_info(dev, "CLS mismatch (%u != %u), using %u bytes\n",
+                                cls << 2, tmp << 2,
+                                pci_dfl_cache_line_size << 2);
                        pci_cache_line_size = pci_dfl_cache_line_size;
                }
        }
 
        if (!pci_cache_line_size) {
-               printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n",
-                      cls << 2, pci_dfl_cache_line_size << 2);
+               pr_info("PCI: CLS %u bytes, default %u\n", cls << 2,
+                       pci_dfl_cache_line_size << 2);
                pci_cache_line_size = cls ? cls : pci_dfl_cache_line_size;
        }
 
@@ -2245,6 +2244,23 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
 
+/*
+ * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
+ * Link bit cleared after starting the link retrain process to allow this
+ * process to finish.
+ *
+ * Affected devices: PI7C9X110, PI7C9X111SL, PI7C9X130.  See also the
+ * Pericom Errata Sheet PI7C9X111SLB_errata_rev1.2_102711.pdf.
+ */
+static void quirk_enable_clear_retrain_link(struct pci_dev *dev)
+{
+       dev->clear_retrain_link = 1;
+       pci_info(dev, "Enable PCIe Retrain Link quirk\n");
+}
+DECLARE_PCI_FIXUP_HEADER(0x12d8, 0xe110, quirk_enable_clear_retrain_link);
+DECLARE_PCI_FIXUP_HEADER(0x12d8, 0xe111, quirk_enable_clear_retrain_link);
+DECLARE_PCI_FIXUP_HEADER(0x12d8, 0xe130, quirk_enable_clear_retrain_link);
+
 static void fixup_rev1_53c810(struct pci_dev *dev)
 {
        u32 class = dev->class;
@@ -2596,7 +2612,7 @@ static void nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
        pci_read_config_dword(dev, 0x74, &cfg);
 
        if (cfg & ((1 << 2) | (1 << 15))) {
-               printk(KERN_INFO "Rewriting IRQ routing register on MCP55\n");
+               pr_info("Rewriting IRQ routing register on MCP55\n");
                cfg &= ~((1 << 2) | (1 << 15));
                pci_write_config_dword(dev, 0x74, cfg);
        }
@@ -3408,6 +3424,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, quirk_no_bus_reset);
 
 /*
  * Root port on some Cavium CN8xxx chips do not successfully complete a bus
@@ -4903,6 +4920,7 @@ static void quirk_no_ats(struct pci_dev *pdev)
 
 /* AMD Stoney platform GPU */
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x98e4, quirk_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6900, quirk_no_ats);
 #endif /* CONFIG_PCI_ATS */
 
 /* Freescale PCIe doesn't support MSI in RC mode */
@@ -5120,3 +5138,61 @@ SWITCHTEC_QUIRK(0x8573);  /* PFXI 48XG3 */
 SWITCHTEC_QUIRK(0x8574);  /* PFXI 64XG3 */
 SWITCHTEC_QUIRK(0x8575);  /* PFXI 80XG3 */
 SWITCHTEC_QUIRK(0x8576);  /* PFXI 96XG3 */
+
+/*
+ * On Lenovo Thinkpad P50 SKUs with a Nvidia Quadro M1000M, the BIOS does
+ * not always reset the secondary Nvidia GPU between reboots if the system
+ * is configured to use Hybrid Graphics mode.  This results in the GPU
+ * being left in whatever state it was in during the *previous* boot, which
+ * causes spurious interrupts from the GPU, which in turn causes us to
+ * disable the wrong IRQ and end up breaking the touchpad.  Unsurprisingly,
+ * this also completely breaks nouveau.
+ *
+ * Luckily, it seems a simple reset of the Nvidia GPU brings it back to a
+ * clean state and fixes all these issues.
+ *
+ * When the machine is configured in Dedicated display mode, the issue
+ * doesn't occur.  Fortunately the GPU advertises NoReset+ when in this
+ * mode, so we can detect that and avoid resetting it.
+ */
+static void quirk_reset_lenovo_thinkpad_p50_nvgpu(struct pci_dev *pdev)
+{
+       void __iomem *map;
+       int ret;
+
+       if (pdev->subsystem_vendor != PCI_VENDOR_ID_LENOVO ||
+           pdev->subsystem_device != 0x222e ||
+           !pdev->reset_fn)
+               return;
+
+       if (pci_enable_device_mem(pdev))
+               return;
+
+       /*
+        * Based on nvkm_device_ctor() in
+        * drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+        */
+       map = pci_iomap(pdev, 0, 0x23000);
+       if (!map) {
+               pci_err(pdev, "Can't map MMIO space\n");
+               goto out_disable;
+       }
+
+       /*
+        * Make sure the GPU looks like it's been POSTed before resetting
+        * it.
+        */
+       if (ioread32(map + 0x2240c) & 0x2) {
+               pci_info(pdev, FW_BUG "GPU left initialized by EFI, resetting\n");
+               ret = pci_reset_function(pdev);
+               if (ret < 0)
+                       pci_err(pdev, "Failed to reset GPU: %d\n", ret);
+       }
+
+       iounmap(map);
+out_disable:
+       pci_disable_device(pdev);
+}
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, 0x13b1,
+                             PCI_CLASS_DISPLAY_VGA, 8,
+                             quirk_reset_lenovo_thinkpad_p50_nvgpu);