drm/i915: Try to detect sudden loss of MMIO access
[linux-2.6-block.git] / drivers / gpu / drm / i915 / intel_uncore.c
index 1c14a07eba7d6f651b7a66208f1f484b20a8f1e6..661b50191f2ba7f11432eab277c77b396b3ce93d 100644 (file)
@@ -465,6 +465,22 @@ fpga_check_for_unclaimed_mmio(struct intel_uncore *uncore)
        if (likely(!(dbg & FPGA_DBG_RM_NOCLAIM)))
                return false;
 
+       /*
+        * Bugs in PCI programming (or failing hardware) can occasionally cause
+        * us to lose access to the MMIO BAR.  When this happens, register
+        * reads will come back with 0xFFFFFFFF for every register and things
+        * go bad very quickly.  Let's try to detect that special case and at
+        * least try to print a more informative message about what has
+        * happened.
+        *
+        * During normal operation the FPGA_DBG register has several unused
+        * bits that will always read back as 0's so we can use them as canaries
+        * to recognize when MMIO accesses are just busted.
+        */
+       if (unlikely(dbg == ~0))
+               drm_err(&uncore->i915->drm,
+                       "Lost access to MMIO BAR; all registers now read back as 0xFFFFFFFF!\n");
+
        __raw_uncore_write32(uncore, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
 
        return true;
@@ -1780,7 +1796,7 @@ static int i915_pmic_bus_access_notifier(struct notifier_block *nb,
 static int uncore_mmio_setup(struct intel_uncore *uncore)
 {
        struct drm_i915_private *i915 = uncore->i915;
-       struct pci_dev *pdev = i915->drm.pdev;
+       struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
        int mmio_bar;
        int mmio_size;
 
@@ -1812,7 +1828,7 @@ static int uncore_mmio_setup(struct intel_uncore *uncore)
 
 static void uncore_mmio_cleanup(struct intel_uncore *uncore)
 {
-       struct pci_dev *pdev = uncore->i915->drm.pdev;
+       struct pci_dev *pdev = to_pci_dev(uncore->i915->drm.dev);
 
        pci_iounmap(pdev, uncore->regs);
 }
@@ -2070,7 +2086,7 @@ int i915_reg_read_ioctl(struct drm_device *dev,
  * This routine waits until the target register @reg contains the expected
  * @value after applying the @mask, i.e. it waits until ::
  *
- *     (I915_READ_FW(reg) & mask) == value
+ *     (intel_uncore_read_fw(uncore, reg) & mask) == value
  *
  * Otherwise, the wait will timeout after @slow_timeout_ms milliseconds.
  * For atomic context @slow_timeout_ms must be zero and @fast_timeout_us
@@ -2126,7 +2142,7 @@ int __intel_wait_for_register_fw(struct intel_uncore *uncore,
  * This routine waits until the target register @reg contains the expected
  * @value after applying the @mask, i.e. it waits until ::
  *
- *     (I915_READ(reg) & mask) == value
+ *     (intel_uncore_read(uncore, reg) & mask) == value
  *
  * Otherwise, the wait will timeout after @timeout_ms milliseconds.
  *