From 5092865601ccaae1409abfa083147276916d6c25 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 5 Nov 2007 05:42:08 +1100 Subject: [PATCH] nouveau: Use a sw method instead of notify interrupt to signal fence completion. --- linux-core/nouveau_fence.c | 4 +- shared-core/nouveau_irq.c | 109 ++++++++++++++++++++++--------------- 2 files changed, 67 insertions(+), 46 deletions(-) diff --git a/linux-core/nouveau_fence.c b/linux-core/nouveau_fence.c index f0e62861..6f3259f0 100644 --- a/linux-core/nouveau_fence.c +++ b/linux-core/nouveau_fence.c @@ -67,9 +67,7 @@ nouveau_fence_emit(struct drm_device *dev, uint32_t class, uint32_t flags, DRM_DEBUG("emit 0x%08x\n", *breadcrumb); BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_REF, 1); OUT_RING (*breadcrumb); - BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); - OUT_RING (NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE_LE_AWAKEN); - BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); + BEGIN_RING(NvSubM2MF, 0x0150, 1); OUT_RING (0); FIRE_RING (); diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index 1a52a584..08bd1da0 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -244,39 +244,53 @@ nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret) return 0; } +struct nouveau_pgraph_trap { + int channel; + int class; + int subc, mthd, size; + uint32_t data, data2; +}; + static void -nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id) +nouveau_graph_trap_info(struct drm_device *dev, + struct nouveau_pgraph_trap *trap) { struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t address; - uint32_t channel, class; - uint32_t method, subc, data, data2; + + if (nouveau_graph_trapped_channel(dev, &trap->channel)) + trap->channel = -1; + address = NV_READ(NV04_PGRAPH_TRAPPED_ADDR); + + trap->mthd = address & 0x1FFC; + trap->data = NV_READ(NV04_PGRAPH_TRAPPED_DATA); + if (dev_priv->card_type < NV_10) { + trap->subc = (address >> 13) & 0x7; + } else { + trap->subc = (address >> 16) & 0x7; + trap->data2 = NV_READ(NV10_PGRAPH_TRAPPED_DATA_HIGH); + } + + if (dev_priv->card_type < NV_10) { + trap->class = NV_READ(0x400180 + trap->subc*4) & 0xFF; + } else if (dev_priv->card_type < NV_40) { + trap->class = NV_READ(0x400160 + trap->subc*4) & 0xFFF; + } else if (dev_priv->card_type < NV_50) { + trap->class = NV_READ(0x400160 + trap->subc*4) & 0xFFFF; + } else { + trap->class = NV_READ(0x400814); + } +} + +static void +nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id, + struct nouveau_pgraph_trap *trap) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t nsource, nstatus; - if (nouveau_graph_trapped_channel(dev, &channel)) - channel = -1; - - data = NV_READ(NV04_PGRAPH_TRAPPED_DATA); - address = NV_READ(NV04_PGRAPH_TRAPPED_ADDR); - method = address & 0x1FFC; - if (dev_priv->card_type < NV_10) { - subc = (address >> 13) & 0x7; - data2= 0; - } else { - subc = (address >> 16) & 0x7; - data2= NV_READ(NV10_PGRAPH_TRAPPED_DATA_HIGH); - } nsource = NV_READ(NV03_PGRAPH_NSOURCE); nstatus = NV_READ(NV03_PGRAPH_NSTATUS); - if (dev_priv->card_type < NV_10) { - class = NV_READ(0x400180 + subc*4) & 0xFF; - } else if (dev_priv->card_type < NV_40) { - class = NV_READ(0x400160 + subc*4) & 0xFFF; - } else if (dev_priv->card_type < NV_50) { - class = NV_READ(0x400160 + subc*4) & 0xFFFF; - } else { - class = NV_READ(0x400814); - } DRM_INFO("%s - nSource:", id); nouveau_print_bitfield_names(nsource, nouveau_nsource_names, @@ -291,37 +305,29 @@ nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id) printk("\n"); DRM_INFO("%s - Ch %d/%d Class 0x%04x Mthd 0x%04x Data 0x%08x:0x%08x\n", - id, channel, subc, class, method, data2, data); + id, trap->channel, trap->subc, trap->class, trap->mthd, + trap->data2, trap->data); } static inline void nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_trap trap; int unhandled = 0; - if (nsource & NV03_PGRAPH_NSOURCE_NOTIFICATION && dev_priv->ttm) { - int channel; - if (!nouveau_graph_trapped_channel(dev, &channel)) { - nouveau_fence_handler(dev, channel); - } - } else - if (dev_priv->card_type == NV_04 && - (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) { - uint32_t class, mthd; + nouveau_graph_trap_info(dev, &trap); + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { /* NV4 (nvidia TNT 1) reports software methods with * PGRAPH NOTIFY ILLEGAL_MTHD */ - mthd = NV_READ(NV04_PGRAPH_TRAPPED_ADDR) & 0x1FFC; - class = NV_READ(NV04_PGRAPH_CTX_SWITCH1) & 0xFFF; DRM_DEBUG("Got NV04 software method method %x for class %#x\n", - mthd, class); + trap.mthd, trap.class); - if (nouveau_sw_method_execute(dev, class, mthd)) { + if (nouveau_sw_method_execute(dev, trap.class, trap.mthd)) { DRM_ERROR("Unable to execute NV04 software method %x " "for object class %x. Please report.\n", - mthd, class); + trap.mthd, trap.class); unhandled = 1; } } else { @@ -329,13 +335,30 @@ nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource) } if (unhandled) - nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY"); + nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap); } static inline void nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource) { - nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR"); + struct nouveau_pgraph_trap trap; + int unhandled = 0; + + nouveau_graph_trap_info(dev, &trap); + + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { + if (trap.channel >= 0 && trap.mthd == 0x0150) { + nouveau_fence_handler(dev, trap.channel); + } else + if (nouveau_sw_method_execute(dev, trap.class, trap.mthd)) { + unhandled = 1; + } + } else { + unhandled = 1; + } + + if (unhandled) + nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR", &trap); } static inline void