Port-atari archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

wdc and DMA interrupt issue



I wrote:

> > Also reading NetBSD 4 installation sets from IDE disk and copying files
> > from IDE to SCSI work, so it seems that wdc_mb.c is not affected by gcc4.
> 
> Then maybe the problem is in softint(9) changes.
> I'll a possible patch later (in a new thread again).

As I noted in this message
http://mail-index.NetBSD.org/port-atari/2008/12/25/msg000159.html
softint(9) is one of major changes in the HEAD since 4.0, and
the DMA interrupt (which is shared with wdc) uses a callback function
which is invoked via the softint(9).

In 4.x kernel, software interrupts are checked and invoked
as soon as a higher priority interrupt is returned from
its handler, and callback functions are called at splsoft().
(see the "rei" fucntion in locore.s)

In the HEAD, software interrupts are now handled in kernel threads,
(as we can see it in sys/kern/kern_softint.c) so callback functions
could have some latency (context switch is required) and
it may run at lower interrupt priority level
(though I have not confirmed it well).

On the other hand, the DMA interrupt handler (cdmaint() in dma.c)
uses BASEPRI() macro which is defined in atari/include/cpu.h,
and it checks %SR register value at the time interrupt occurs.

If the interrupt occurs during another interrupt is being
processed, the queued DMA interrupt handler is scheduled
to be executed later via add_sicallback() function.
If the cdmaint() is not come from interrupt handlers,
it calls the queued interrupt handler directly.

In wdc case, the wdcintr() function will be called from cdmaint()
or via the callback function since it's queued via st_dmagrab()
in claim_hw() function.

If -current softint(9) functions are no longer executed at
splsoft() but at BASEPRI, wdcintr() could be called recursively
if another wdc interrupt occurs during wdcintr() invoked from
the callback is being processed.
(I haven't tracked this closely though)

One possible and simple workaround is to raise IPL to splsoft()
before invoking callback functions as if old kernels did in locore.s:
---
Index: atari/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/atari/atari/machdep.c,v
retrieving revision 1.154
diff -u -r1.154 machdep.c
--- atari/machdep.c     30 Nov 2008 18:21:32 -0000      1.154
+++ atari/machdep.c     2 Jan 2009 01:14:27 -0000
@@ -810,7 +810,9 @@
                        si->next = si_free;
                        si_free  = si;
                        splx(s);
+                       s = splsoftnet();       /* XXX */
                        function(rock1, rock2);
+                       splx(s);
                }
        } while (si);
 #ifdef DIAGNOSTIC

---
so that BASEPRI() returns false even if nested DMA (or wdc) interrupt
occurs and the next wdcintr() is scheduled to be invoked later
(i.e. after current wdcintr() returns).

Could you try this one?
http://www.ceres.dti.ne.jp/~tsutsui/netbsd/netbsd-ATARITT-HEAD-20090102.gz
http://www.ceres.dti.ne.jp/~tsutsui/netbsd/netbsd-BOOT-HEAD-20090102.gz
http://www.ceres.dti.ne.jp/~tsutsui/netbsd/netbsd-FALCON-HEAD-20090102.gz

I wonder if the right solution is to raise IPL to splbio()
before calling wdcintr() (and maybe also ncr_dma_intr() and
ncr_ctrl_intr() in ncr5380.c) from the callback function
to block nested interrupts properly, though...

IMO, all uses of the callback function (which is atari specific)
should be rewritten to use the MI softint(9) directly, though
it doesn't have capability to cancel scheduled handlers as
machdep.c:rem_sicallback() does...
---
Izumi Tsutsui


Home | Main Index | Thread Index | Old Index