/** * i965_reset - reset chip after a hang * @dev: drm device to reset * @flags: reset domains * * Reset the chip. Useful if a hang is detected. Returns zero on successful * reset or otherwise an error code. * * Procedure is fairly simple: * - reset the chip using the reset reg * - re-init context state * - re-init hardware status page * - re-init ring buffer * - re-init interrupt state * - re-init display */ int i915_reset(struct drm_device *dev, u8 flags) { drm_i915_private_t *dev_priv = dev->dev_private; /* * We really should only reset the display subsystem if we actually * need to */ bool need_display = true; int ret; if (!i915_try_reset) return 0; if (!mutex_trylock(&dev->struct_mutex)) return -EBUSY; i915_gem_reset(dev); ret = -ENODEV; if (get_seconds() - dev_priv->last_gpu_reset < 5) { DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); } else switch (INTEL_INFO(dev)->gen) { case 7: case 6: ret = gen6_do_reset(dev, flags); break; case 5: ret = ironlake_do_reset(dev, flags); break; case 4: ret = i965_do_reset(dev, flags); break; case 2: ret = i8xx_do_reset(dev, flags); break; } dev_priv->last_gpu_reset = get_seconds(); if (ret) { DRM_ERROR("Failed to reset chip.\n"); mutex_unlock(&dev->struct_mutex); return ret; } /* Ok, now get things going again... */ /* * Everything depends on having the GTT running, so we need to start * there. Fortunately we don't need to do this unless we reset the * chip at a PCI level. * * Next we need to restore the context, but we don't use those * yet either... * * Ring buffer needs to be re-initialized in the KMS case, or if X * was running at the time of the reset (i.e. we weren't VT * switched away). */ if (drm_core_check_feature(dev, DRIVER_MODESET) || !dev_priv->mm.suspended) { dev_priv->mm.suspended = 0; dev_priv->ring[RCS].init(&dev_priv->ring[RCS]); if (HAS_BSD(dev)) dev_priv->ring[VCS].init(&dev_priv->ring[VCS]); if (HAS_BLT(dev)) dev_priv->ring[BCS].init(&dev_priv->ring[BCS]); mutex_unlock(&dev->struct_mutex); drm_irq_uninstall(dev); drm_mode_config_reset(dev); drm_irq_install(dev); mutex_lock(&dev->struct_mutex); } mutex_unlock(&dev->struct_mutex); /* * Perform a full modeset as on later generations, e.g. Ironlake, we may * need to retrain the display link and cannot just restore the register * values. */ if (need_display) { mutex_lock(&dev->mode_config.mutex); drm_helper_resume_force_mode(dev); mutex_unlock(&dev->mode_config.mutex); } return 0; }
int i915_reset(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; /* * We really should only reset the display subsystem if we actually * need to */ bool need_display = true; int ret; if (!i915_try_reset) return (0); if (!sx_try_xlock(&dev->dev_struct_lock)) return (-EBUSY); i915_gem_reset(dev); ret = -ENODEV; if (time_second - dev_priv->last_gpu_reset < 5) { DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); } else ret = intel_gpu_reset(dev); dev_priv->last_gpu_reset = time_second; if (ret) { DRM_ERROR("Failed to reset chip.\n"); DRM_UNLOCK(dev); return (ret); } if (drm_core_check_feature(dev, DRIVER_MODESET) || !dev_priv->mm.suspended) { dev_priv->mm.suspended = 0; i915_gem_init_swizzling(dev); dev_priv->rings[RCS].init(&dev_priv->rings[RCS]); if (HAS_BSD(dev)) dev_priv->rings[VCS].init(&dev_priv->rings[VCS]); if (HAS_BLT(dev)) dev_priv->rings[BCS].init(&dev_priv->rings[BCS]); i915_gem_context_init(dev); i915_gem_init_ppgtt(dev); drm_irq_uninstall(dev); drm_mode_config_reset(dev); DRM_UNLOCK(dev); drm_irq_install(dev); DRM_LOCK(dev); } DRM_UNLOCK(dev); if (need_display) { sx_xlock(&dev->mode_config.mutex); drm_helper_resume_force_mode(dev); sx_xunlock(&dev->mode_config.mutex); } return (0); }
int i915_reset(struct drm_device *dev, u8 flags) { drm_i915_private_t *dev_priv = dev->dev_private; bool need_display = true; int ret; if (!i915_try_reset) return 0; if (!mutex_trylock(&dev->struct_mutex)) return -EBUSY; i915_gem_reset(dev); ret = -ENODEV; if (get_seconds() - dev_priv->last_gpu_reset < 5) { DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); } else switch (INTEL_INFO(dev)->gen) { case 7: case 6: ret = gen6_do_reset(dev, flags); break; case 5: ret = ironlake_do_reset(dev, flags); break; case 4: ret = i965_do_reset(dev, flags); break; case 2: ret = i8xx_do_reset(dev, flags); break; } dev_priv->last_gpu_reset = get_seconds(); if (ret) { DRM_ERROR("Failed to reset chip.\n"); mutex_unlock(&dev->struct_mutex); return ret; } if (drm_core_check_feature(dev, DRIVER_MODESET) || !dev_priv->mm.suspended) { dev_priv->mm.suspended = 0; i915_gem_init_swizzling(dev); dev_priv->ring[RCS].init(&dev_priv->ring[RCS]); if (HAS_BSD(dev)) dev_priv->ring[VCS].init(&dev_priv->ring[VCS]); if (HAS_BLT(dev)) dev_priv->ring[BCS].init(&dev_priv->ring[BCS]); i915_gem_init_ppgtt(dev); mutex_unlock(&dev->struct_mutex); drm_irq_uninstall(dev); drm_mode_config_reset(dev); drm_irq_install(dev); mutex_lock(&dev->struct_mutex); } mutex_unlock(&dev->struct_mutex); if (need_display) { mutex_lock(&dev->mode_config.mutex); drm_helper_resume_force_mode(dev); mutex_unlock(&dev->mode_config.mutex); } return 0; }
void intel_batch_submit(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); int ret; assert (!intel->in_batch_atomic); if (intel->vertex_flush) intel->vertex_flush(intel); intel_end_vertex(intel); if (intel->batch_flush) intel->batch_flush(intel); if (intel->batch_used == 0) return; /* Mark the end of the batchbuffer. */ OUT_BATCH(MI_BATCH_BUFFER_END); /* Emit a padding dword if we aren't going to be quad-word aligned. */ if (intel->batch_used & 1) OUT_BATCH(MI_NOOP); if (DUMP_BATCHBUFFERS) { FILE *file = fopen(DUMP_BATCHBUFFERS, "a"); if (file) { fwrite (intel->batch_ptr, intel->batch_used*4, 1, file); fclose(file); } } ret = dri_bo_subdata(intel->batch_bo, 0, intel->batch_used*4, intel->batch_ptr); if (ret == 0) { ret = drm_intel_bo_mrb_exec(intel->batch_bo, intel->batch_used*4, NULL, 0, 0xffffffff, (HAS_BLT(intel) ? intel->current_batch: I915_EXEC_DEFAULT)); } if (ret != 0) { static int once; if (!once) { if (ret == -EIO) { /* The GPU has hung and unlikely to recover by this point. */ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Detected a hung GPU, disabling acceleration.\n"); xf86DrvMsg(scrn->scrnIndex, X_ERROR, "When reporting this, please include i915_error_state from debugfs and the full dmesg.\n"); } else { /* The driver is broken. */ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to submit batch buffer, expect rendering corruption: %s.\n ", strerror(-ret)); } uxa_set_force_fallback(xf86ScrnToScreen(scrn), TRUE); intel->force_fallback = TRUE; once = 1; } } while (!list_is_empty(&intel->batch_pixmaps)) { struct intel_pixmap *entry; entry = list_first_entry(&intel->batch_pixmaps, struct intel_pixmap, batch); entry->busy = -1; entry->dirty = 0; list_del(&entry->batch); } if (intel->debug_flush & DEBUG_FLUSH_WAIT) drm_intel_bo_wait_rendering(intel->batch_bo); intel_next_batch(scrn, intel->current_batch == I915_EXEC_BLT); if (intel->batch_commit_notify) intel->batch_commit_notify(intel); intel->current_batch = 0; }