Hi,
I agree that this issue is not quite good described in the documents, so I'll post my principles of using it. 1. I always use interruptible_*() calls. I didn't have a hardware device which would have been confused by it. 2. In the init_*() function, I always probe for a device and if successful, I reserve the io space and the irq. I also maintain one 'struct wait_queue *' for each /dev/* file I am supporting with my driver. Here I initiate this pointer to be NULL. I do not allow device to generate interrupts yet. 3. In open_*() function, I initiate input and output buffers for device, and enable it to generate interrupts. 4. In read_*() and write_*() functions, I look if something can be read/written from/to the input/output buffers and do it. I look if the operation has completed (all bytes read/written). If yes, I return. If not, I look at the O_NONBLOCK flag and return -EWOULDBLOCK if this flag is set, otherwise I call sleep_on_interruptible(&wait_queue), with the address of my pointer as the argument. When I'm woken up, I look if (current->signal & ~current->blocked) is set. If yes, I return -EINTR, otherwise I repeat the step 4 again to read/write more bytes. 5. In my interrupt handling routine I first figure out which device generated it, finding in such a way it's corresponding 'struct wait_queue *' and input/output buffers. Then I do the io operations, using the data in input/output buffers. At the end, I call wake_up_interruptible(&wait_queue). 6. In close() I usually disable device generating interrupts, and optionally call wake_up_interruptible(), just to be sure. NOTE 1: You do not maintain the structure, only the pointer to the 'struct wait_queue'. The queue is beeing maintained behind sleep_*() wake_up_*() calls. Empty queue <-> NULL pointer. NOTE 2: The biggest problem is to do the right action when the device generates an interrupt. You should study documentation for your device very carefully. I always have fears that the interrupt will be generated when I am not prepared to handle it (device not opened, no input/output buffers). NOTE 3: The other problem is to ensure the things going on when you are not able to handle an interrupt immediatelly. Suppose that device has notified you that there is some input data pending, but you have no input buffers available to acquire it. So, you have to note this case, and handle it properly in your read() function, where you actually free the input buffers. However, normally you do the io operations in the interrupt handling routine, beeing non-preemptive. So, you have to mask the interrupt and then do the io operations... There are some more fine things in the adventure of writing device drivers story, but you have to find them out alone, and they depend a lot on the hardware interface provided. In few words, be VERY, VERY careful, hendling interrupts is far from a trivial task and may easy couse you system to hang. Hope it helps. Miran
|