I2C read/write transfers are NOT deterministic.
The protocol allows peripheral slave ICs to perform clock stretching thereby allowing them to "hold" the master until they are ready. However this is NOT a common scenario and hence each I2C transfer usually completes in a pre-determined interval most of the time. However, it is NOT a guarantee, and hence NOT a good idea to perform several I2C transfers within an ISR.
This link contains a nice explanation about the fundamentals of threaded irqs and their proper usage.
Optimal design for the above scenario ?
Using threaded-interrupt handler approach will not have many benefits as attempting to enable/disable the interrupts on the device will add to the latency.
In your current scenario (single interrupt from single device), one can stick to the regular request_irq()
to register an interrupt service routine(ISR).
ISR code :
1. In the ISR, call disable_irq()
to prevent further interrupts.
2. Schedule a bottom half handler function (workqueue is a good choice).
3. Return IRQ_HANDLED
from the ISR.
Bottom-half handler code :
4. Perform I2C transfers.
5. Call enable_irq()
and exit.
NOTE :
Another way to implement the same design would be to use a threaded-irq without an ISR. This achieves the same as the above design and eliminates the need to define/initialise/cleanup the bottom-half handler separately in your code.
In this approach one would put all the I2C read/write code within the IRQ thread function and pass it to request_threaded_irq()
along-with handler = NULL
i.e. an empty ISR.