I've just had the misfortune of having my NFSROOT system (lots of network
interrupts), have its card sharing interrupts with the i810 graphics..
once I run anything 3d the kernel oops..

The attached patch contains the quick fix which is to check in thr irq
handler if dev->dev_private is NULL or not before going using it .. also a
udelay patch included which I think the DRI tree has but the LK one
doesn't....(arrgg too many trees :-)..

I've attached a second patch to
xc/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c that may also
fix the problem but which I haven't tested,

What happens is the DMA cleanup occurs which frees the private data, and
an interrupt comes in from the network card most likely but the i810
driver is let know as the IRQ hasn't been deregistered yet..

This issue also will affect the i830 and gamma (not that anyone cares) but
maybe others as well as my DRI tree is old enough at this stage....

Dave.

-- 
David Airlie, Software Engineer
http://www.skynet.ie/~airlied / [EMAIL PROTECTED]
pam_smb / Linux DecStation / Linux VAX / ILUG person
Index: drivers/char/drm/i810_dma.c
===================================================================
RCS file: /home/sapphire/saphcvs/kernel-2.4/drivers/char/drm/i810_dma.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 i810_dma.c
--- drivers/char/drm/i810_dma.c 26 Feb 2003 01:37:26 -0000      1.1.1.2
+++ drivers/char/drm/i810_dma.c 24 Mar 2003 04:01:46 -0000
@@ -36,6 +36,7 @@
 #include "i810_drv.h"
 #include <linux/interrupt.h>   /* For task queue support */
 #include <linux/module.h>
+#include <linux/delay.h>
 
 /* in case we don't have a 2.3.99-pre6 kernel or later: */
 #ifndef VM_DONTCOPY
@@ -317,7 +318,7 @@
                        goto out_wait_ring;
                }
 
-               for (i = 0 ; i < 2000 ; i++) ;
+               udelay(1);
        }
 
 out_wait_ring:
@@ -894,19 +895,23 @@
 void i810_dma_service(int irq, void *device, struct pt_regs *regs)
 {
        drm_device_t     *dev = (drm_device_t *)device;
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+       drm_i810_private_t *dev_priv;
        u16 temp;
 
-       atomic_inc(&dev->counts[_DRM_STAT_IRQ]);
-       temp = I810_READ16(I810REG_INT_IDENTITY_R);
-       temp = temp & ~(0x6000);
-       if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R,
+       if (dev->dev_private) {
+               dev_priv = (drm_i810_private_t *)dev->dev_private;
+               
+               atomic_inc(&dev->counts[_DRM_STAT_IRQ]);
+               temp = I810_READ16(I810REG_INT_IDENTITY_R);
+               temp = temp & ~(0x6000);
+               if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R,
                                   temp); /* Clear all interrupts */
-       else
-          return;
+               else
+                  return;
 
-       queue_task(&dev->tq, &tq_immediate);
-       mark_bh(IMMEDIATE_BH);
+               queue_task(&dev->tq, &tq_immediate);
+               mark_bh(IMMEDIATE_BH);
+       }
 }
 
 void i810_dma_immediate_bh(void *device)
--- xc/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c.orig      2003-03-24 
15:17:38.000000000 +1100
+++ xc/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c   2003-03-24 
15:19:00.000000000 +1100
@@ -949,6 +949,11 @@
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I810Ptr pI810 = I810PTR(pScrn);

+   if (info->irq) {
+      drmCtlUninstHandler(pI810->drmSubFD);
+      info->irq = 0;
+   }
+
    I810CleanupDma(pScrn);

    if (pI810->dcacheHandle)

Reply via email to