summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/nouveau_state.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c
index 5b67aea1..a26ecea3 100644
--- a/shared-core/nouveau_state.c
+++ b/shared-core/nouveau_state.c
@@ -522,16 +522,31 @@ int nouveau_ioctl_setparam(DRM_IOCTL_ARGS)
void nouveau_wait_for_idle(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv=dev->dev_private;
- switch(dev_priv->card_type)
- {
- case NV_03:
- while(NV_READ(NV03_PGRAPH_STATUS));
- break;
- case NV_50:
- break;
- default:
- while(NV_READ(NV04_PGRAPH_STATUS));
- break;
+ switch(dev_priv->card_type) {
+ case NV_03:
+ while (NV_READ(NV03_PGRAPH_STATUS));
+ break;
+ case NV_50:
+ break;
+ default: {
+ /* This stuff is more or less a copy of what is seen
+ * in nv28 kmmio dump.
+ */
+ uint64_t started = dev_priv->Engine.timer.read(dev);
+ uint64_t stopped = started;
+ uint32_t status;
+ do {
+ uint32_t pmc_e = NV_READ(NV03_PMC_ENABLE);
+ status = NV_READ(NV04_PGRAPH_STATUS);
+ if (!status)
+ break;
+ stopped = dev_priv->Engine.timer.read(dev);
+ /* It'll never wrap anyway... */
+ } while (stopped - started < 1000000000ULL);
+ if (status)
+ DRM_ERROR("timed out with status 0x%08x\n",
+ status);
+ }
}
}