In my system I'm using I2C to 2xUART converter SC16IS752. Linux Kernel sources already has driver for this chip, but only in SPI mode. Now I trying to modify this driver for I2C work. I2C has speed 400 kHz. To this converter's UART connected device on baud 38400. This device every 1s sends packets containing about 100 bytes data. SC16IS752 has 64 bytes RX FIFO, so it must be handled two times per one packet.
And I faced the problem of long latencies. When FIFO reaches threshold value, hardware interrupt occurs and now executes IRQ handler:
static irqreturn_t sc16is7x2_irq(int irq, void *data)
{
struct sc16is7x2_channel *chan = data;
#ifdef DEBUG
/* Indicate irq */
chan->handle_irq = true;
#endif
/* Trigger work thread */
sc16is7x2_dowork(chan);
return IRQ_HANDLED;
}
static void sc16is7x2_dowork(struct sc16is7x2_channel *chan)
{
printk("sc16is7x2_dowork \n");
if(!freezing(current))
{
queue_work(chan->workqueue, &chan->work);
}
}
So, as you can see, interrupt handler puts work for handle data from SC16IS752 FIFO in the queue.
And here i faced with problem. sc16is7x2_irq function executes immediately after interrupt occurs. But queued work is performed within 25ms after interrupt occurs. But after this time, FIFO is overflowed and data lost (100 bytes transmits in 26ms).
What is the correct solution in this situation and how to reduce 25ms latency in Linux Kernel?