Hi,

While running debian's gnumach 20050501-4 on qemu and some heavy IDE
disk load, I sometimes get an "unexpected interrupt" error, then
disk operations hang, and finally an "irq timeout" error occurs, and
things work again. I also sometimes observed the same behavior on the
real machine, though quite more rarely (but maybe Marcus can remember me
listening to my hard drive at lsm :) ).

Actually, in several places, the ide functions sends IDE orders _before_
setting the irq handler, and qemu seems to be fast to send the interrupt
back, this latter is hence unexpected that soon. Here is a patch
(patch-gnumach-ide) to correct this. It is needed when the unmask drive
field is set.

But in my case, the unmask field was not set... The errors I got were
also coming from a complementary bug:

The ide_intr() expects its caller to have disabled interrupts already,
this is expressed by the SA_INTERRUPT flag in the request_irq()
call. However, I tried and noticed that interrupts are _not_ disabled
by the caller. The gnumach interrupt handler i386/i386at/interrup.S does
not disable interrupts, and linux_intr() does not either. Here is a patch
(patch-gnumach-irq) to make linux_intr() care about that. I guess several
other device drivers will probably be happier with this bugfix.

Regards,
Samuel
--- gnumach/linux/dev/drivers/block/ide.c       2001-06-28 10:55:02.000000000 
+0200
+++ gnumach/linux/dev/drivers/block/ide.c       2005-07-19 03:53:36.000000000 
+0200
@@ -1129,6 +1129,9 @@
                msect -= nsect;
        } else
                nsect = 1;
+       i = rq->nr_sectors - nsect;
+       if (i > 0 && !msect)
+               ide_set_handler (drive, &read_intr, WAIT_CMD);
        ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
 #ifdef DEBUG
        printk("%s:  read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n",
@@ -1138,14 +1141,11 @@
        rq->sector += nsect;
        rq->buffer += nsect<<9;
        rq->errors = 0;
-       i = (rq->nr_sectors -= nsect);
+       rq->nr_sectors = i;
        if ((rq->current_nr_sectors -= nsect) <= 0)
                ide_end_request(1, HWGROUP(drive));
-       if (i > 0) {
-               if (msect)
-                       goto read_next;
-               ide_set_handler (drive, &read_intr, WAIT_CMD);
-       }
+       if (i > 0 && msect)
+               goto read_next;
 }
 
 /*
@@ -1173,8 +1173,8 @@
                        if (rq->current_nr_sectors <= 0)
                                ide_end_request(1, hwgroup);
                        if (i > 0) {
+                               ide_set_handler (drive, &write_intr, WAIT_CMD);
                                ide_output_data (drive, rq->buffer, 
SECTOR_WORDS);
-                               ide_set_handler (drive, &write_intr, WAIT_CMD);
                        }
                        return;
                }
@@ -1231,8 +1231,8 @@
        if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
                if (stat & DRQ_STAT) {
                        if (rq->nr_sectors) {
+                               ide_set_handler (drive, &multwrite_intr, 
WAIT_CMD);
                                ide_multwrite(drive, drive->mult_count);
-                               ide_set_handler (drive, &multwrite_intr, 
WAIT_CMD);
                                return;
                        }
                } else {
--- gnumach/linux/dev/arch/i386/kernel/irq.c    1999-04-26 07:40:55.000000000 
+0200
+++ gnumach/linux/dev/arch/i386/kernel/irq.c    2005-07-19 04:37:17.000000000 
+0200
@@ -103,16 +103,23 @@ linux_intr (int irq)
 {
   struct pt_regs regs;
   struct linux_action *action = *(irq_action + irq);
+  unsigned long flags;
 
   kstat.interrupts[irq]++;
   intr_count++;
 
+  save_flags (flags);
+  if (action && (action->flags & SA_INTERRUPT))
+    cli ();
+
   while (action)
     {
       action->handler (irq, action->dev_id, &regs);
       action = action->next;
     }
 
+  restore_flags (flags);
+
   intr_count--;
 
   /* Not used. by OKUJI Yoshinori. */
_______________________________________________
Bug-hurd mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-hurd

Reply via email to