OSDN Git Service

nouveau: Use a sw method instead of notify interrupt to signal fence completion.
authorBen Skeggs <skeggsb@gmail.com>
Sun, 4 Nov 2007 18:42:08 +0000 (05:42 +1100)
committerBen Skeggs <skeggsb@gmail.com>
Sun, 4 Nov 2007 18:46:26 +0000 (05:46 +1100)
linux-core/nouveau_fence.c
shared-core/nouveau_irq.c

index f0e6286..6f3259f 100644 (file)
@@ -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 ();
 
index 1a52a58..08bd1da 100644 (file)
@@ -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;
-       uint32_t nsource, nstatus;
 
-       if (nouveau_graph_trapped_channel(dev, &channel))
-               channel = -1;
-
-       data    = NV_READ(NV04_PGRAPH_TRAPPED_DATA);
+       if (nouveau_graph_trapped_channel(dev, &trap->channel))
+               trap->channel = -1;
        address = NV_READ(NV04_PGRAPH_TRAPPED_ADDR);
-       method  = address & 0x1FFC;
+
+       trap->mthd = address & 0x1FFC;
+       trap->data = NV_READ(NV04_PGRAPH_TRAPPED_DATA);
        if (dev_priv->card_type < NV_10) {
-               subc = (address >> 13) & 0x7;
-               data2= 0;
+               trap->subc  = (address >> 13) & 0x7;
        } else {
-               subc = (address >> 16) & 0x7;
-               data2= NV_READ(NV10_PGRAPH_TRAPPED_DATA_HIGH);
+               trap->subc  = (address >> 16) & 0x7;
+               trap->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;
+               trap->class = NV_READ(0x400180 + trap->subc*4) & 0xFF;
        } else if (dev_priv->card_type < NV_40) {
-               class = NV_READ(0x400160 + subc*4) & 0xFFF;
+               trap->class = NV_READ(0x400160 + trap->subc*4) & 0xFFF;
        } else if (dev_priv->card_type < NV_50) {
-               class = NV_READ(0x400160 + subc*4) & 0xFFFF;
+               trap->class = NV_READ(0x400160 + trap->subc*4) & 0xFFFF;
        } else {
-               class = NV_READ(0x400814);
+               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;
+
+       nsource = NV_READ(NV03_PGRAPH_NSOURCE);
+       nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
 
        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