[OFFTOPIC] Basic Device Driver Question

Ken Treis (treisk@wwics.com)
Tue, 10 Jun 1997 17:52:45 -0700 (PDT)


Sorry to post this here, but my news server access has been cut off -
or I'd have hit comp.os.linux.development.system..

I'm writing device drivers for my company, and we're trying to port some
pretty hefty applications to Linux from both Interactive Unix and WinNT.

Here's the difficulty I'm having. I'm porting a driver from interactive,
and the old driver used physical IO. I'm familiar enough with the
threads on this list to know that physical IO, in the sense that most
AT&T unixes know it, is no implemented on Linux and may never be. This
is fine with me.. I can transfer to a kmalloc'd buffer and memcpy_tofs.

I'm transfering large chunks of data, though.. from 4 to 8 MB in a shot
(it's a company-proprietary video capture board). This is obviously too
much to malloc in the kernel -- kmalloc won't allow it, and it'd probably
be absurd if it did -- so I have to transfer parts of the image at a time,
copying the data out to user space between parts.

My driver works, for the most part -- but I'm getting errors about half
of the time when transfering 1024 lines. Errors occur when the 16k EISA
FIFO fills completely -- i.e., the DMAs didn't pull it from the fifo
quickly enough. I've set up a routine that does something like this:

foo_read()
{
/* Tell Board to go.. */

cli();

/* Unmask EISA FIFO .. it starts filling here */

while (!done) {
ntrans = setup_dma; /* sets DMA addr. and count based */
enable_dma(foo_dma); /* on data quantity in FIFO */
sleep_on(&foo_wait); /* wait for ISR to wake_up */

/* check errors once awake .. if errors, break; */
/* calculate userland address */
/* verify_area */
memcpy_tofs(uaddr, kbufaddr, ntrans);
}
sti();
}

foo_interrupt()
{
/* Check Errors */
/* If errors, increment error counts
wake_up(&foo_wait);
}

Reasons for doing it this way are, to me, pretty straightforward.. can't
memcpy_tofs from an ISR, so we do it in the foo_read function. I've also
locked the userland buffer with mlockall(), so that we shouldn't have any
of the implicit IO problems of using memcpy_tofs in critical sections.

But my driver is being pre-empted somehow, or isn't waking up quickly
enough. I've cleared interrupts, so pre-emption shouldn't be a concern.
I think it's just not waking up quickly enough.

This happens even when I comment out the verify_area and memcpy_tofs ..
we're just not making it around the loop fast enough.

So how do I keep from being pre-empted? The scheduler tries to squeeze
whatever it can into the time while I'm asleep. I have a feeling that
I'm just missing something.

Am I misunderstanding some part of driver semantics? Any help would be
greatly appreciated. Please send messages directly to me so as to keep
the kernel list from becoming any more cluttered.

Thanks!

Ken Treis
treisk@wwics.com