[wakeup before sleep problem]
Try using a short circular buffer for the data and modify your
routines as follows
> the read function has something like this:
> .....
> outb (ioport, 0xFF); /* Ask for data */
> interruptible_sleep_on (&wait_q); /* waits for the interrupt */
> data = inb (ioport); /* grabs the data */
move the above line into the ISR and modify like this:
down(&datasem);
cbuf[tail++] = inb (ioport);
if (tail > MAX_ELEMENTS) tail=0; /* that's, why it's circular ;) */
up(&datasem);
wake_up_interruptible(&wait_q);
/* check for ringbuffer overflows here! Delete the oldest
* element, if overflow and count it as an error.
*/
and in your read function sth. like this
down(&datasem);
if (head != tail)
data = cbuf[head++];
else
/* your reader EAGAIN as an error if in O_NONBLOCK */
if (head > MAX_ELEMENTS) head=0; /* that's, why it's circular ;) */
up(&datasem)
You can even readout the whole buffer or at least as much as fits
into of the buffer given to your read file operation.
remain = buflen; /* 3rd parameter of fops->read */
count = 0;
/* "*userbuf" is the 2nd parameter of fops->read
* and valid for writing "buflen" bytes into it
*/
down(&datasem);
while (remain && head != tail) {
userbuf[count++] = cbuf[head++];
if (head > MAX_ELEMENTS) head=0; /* that's, why it's circular ;) */
remain--;
};
up(&datasem)
My solution is _NOT_ considered optimal, but should work. I
assumed, that your "cbuf" is a _byte_ buffer and that you return
"count" as a result.
> I need the data as fast as I can get (that's fundamental in the
> project), so I am trying to avoid a delay loop, and I guess it would
> slow things a bit in the system also.
Hmm, you better design your hardware to have it wait (may be
still collecting data into a small FIFO?) until you ack the
interrupt or read the data inside the ISR _before_ you ack the
interrupt to the PIC[1] (as I suggested).
> What I need to solve this, is a way to detect (in the interrupt
> handler) that the function is not sleeping yet.
No, this is IMHO the wrong direction for solving your problem.
Hope this helps a bit and works ;)
Regards
Ingo Oeser
[1] Programmable Interrupt Controller.
-- Feel the power of the penguin - run linux@your.pc <esc>:x
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/