drm/nvd0/disp: do modeset irq handling from tasklet
authorBen Skeggs <bskeggs@redhat.com>
Fri, 8 Jul 2011 03:17:01 +0000 (13:17 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 20 Sep 2011 06:07:42 +0000 (16:07 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvd0_display.c

index 1a561d30821517f0bf0b4d93e2c59061c6d49a1c..b6a8c6def64cd7cfc353b0b28d31b2c61ca16ea7 100644 (file)
@@ -44,9 +44,12 @@ struct nvd0_display {
                dma_addr_t handle;
                u32 *ptr;
        } evo[1];
+
+       struct tasklet_struct tasklet;
        struct {
                struct dcb_entry *dis;
                struct dcb_entry *ena;
+               u32 modeset;
                int crtc;
                int pclk;
                u16 cfg;
@@ -1114,9 +1117,24 @@ ack:
        nv_wr32(dev, 0x6101d0, 0x80000000);
 }
 
+static void
+nvd0_display_bh(unsigned long data)
+{
+       struct drm_device *dev = (struct drm_device *)data;
+       struct nvd0_display *disp = nvd0_display(dev);
+
+       if (disp->irq.modeset & 0x00000001)
+               nvd0_display_unk1_handler(dev);
+       if (disp->irq.modeset & 0x00000002)
+               nvd0_display_unk2_handler(dev);
+       if (disp->irq.modeset & 0x00000004)
+               nvd0_display_unk4_handler(dev);
+}
+
 static void
 nvd0_display_intr(struct drm_device *dev)
 {
+       struct nvd0_display *disp = nvd0_display(dev);
        u32 intr = nv_rd32(dev, 0x610088);
 
        if (intr & 0x00000002) {
@@ -1141,14 +1159,10 @@ nvd0_display_intr(struct drm_device *dev)
                u32 stat = nv_rd32(dev, 0x6100ac);
 
                if (stat & 0x00000007) {
-                       nv_wr32(dev, 0x6100ac, (stat & 0x00000007));
+                       disp->irq.modeset = stat;
+                       tasklet_schedule(&disp->tasklet);
 
-                       if (stat & 0x00000001)
-                               nvd0_display_unk1_handler(dev);
-                       if (stat & 0x00000002)
-                               nvd0_display_unk2_handler(dev);
-                       if (stat & 0x00000004)
-                               nvd0_display_unk4_handler(dev);
+                       nv_wr32(dev, 0x6100ac, (stat & 0x00000007));
                        stat &= ~0x00000007;
                }
 
@@ -1371,6 +1385,7 @@ nvd0_display_create(struct drm_device *dev)
        }
 
        /* setup interrupt handling */
+       tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev);
        nouveau_irq_register(dev, 26, nvd0_display_intr);
 
        /* hash table and dma objects for the memory areas we care about */