Skip to content

Commit e6103cd

Browse files
Alain Volmatwsakernel
authored andcommitted
i2c: stm32f7: perform most of irq job in threaded handler
The irq handling is currently split between the irq handler and the threaded irq handler. Some of the handling (such as dma related stuffs) done within the irq handler might sleep or take some time leading to issues if the kernel is built with realtime constraints. In order to fix that, perform an overall rework to perform most of the job within the threaded handler and only keep fifo access in the non threaded handler. Signed-off-by: Alain Volmat <[email protected]> Reviewed-by: Andi Shyti <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent a51e224 commit e6103cd

File tree

1 file changed

+56
-70
lines changed

1 file changed

+56
-70
lines changed

drivers/i2c/busses/i2c-stm32f7.c

Lines changed: 56 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,17 +1497,11 @@ static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev)
14971497
static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
14981498
{
14991499
struct stm32f7_i2c_dev *i2c_dev = data;
1500-
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
1501-
struct stm32_i2c_dma *dma = i2c_dev->dma;
1502-
void __iomem *base = i2c_dev->base;
1503-
u32 status, mask;
1504-
int ret = IRQ_HANDLED;
1500+
u32 status;
15051501

1506-
/* Check if the interrupt if for a slave device */
1507-
if (!i2c_dev->master_mode) {
1508-
ret = stm32f7_i2c_slave_isr_event(i2c_dev);
1509-
return ret;
1510-
}
1502+
/* Check if the interrupt is for a slave device */
1503+
if (!i2c_dev->master_mode)
1504+
return IRQ_WAKE_THREAD;
15111505

15121506
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
15131507

@@ -1519,6 +1513,29 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
15191513
if (status & STM32F7_I2C_ISR_RXNE)
15201514
stm32f7_i2c_read_rx_data(i2c_dev);
15211515

1516+
/* Wake up the thread if other flags are raised */
1517+
if (status &
1518+
(STM32F7_I2C_ISR_NACKF | STM32F7_I2C_ISR_STOPF |
1519+
STM32F7_I2C_ISR_TC | STM32F7_I2C_ISR_TCR))
1520+
return IRQ_WAKE_THREAD;
1521+
1522+
return IRQ_HANDLED;
1523+
}
1524+
1525+
static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
1526+
{
1527+
struct stm32f7_i2c_dev *i2c_dev = data;
1528+
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
1529+
struct stm32_i2c_dma *dma = i2c_dev->dma;
1530+
void __iomem *base = i2c_dev->base;
1531+
u32 status, mask;
1532+
int ret;
1533+
1534+
if (!i2c_dev->master_mode)
1535+
return stm32f7_i2c_slave_isr_event(i2c_dev);
1536+
1537+
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
1538+
15221539
/* NACK received */
15231540
if (status & STM32F7_I2C_ISR_NACKF) {
15241541
dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n",
@@ -1531,33 +1548,28 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
15311548
f7_msg->result = -ENXIO;
15321549
}
15331550

1534-
/* STOP detection flag */
1535-
if (status & STM32F7_I2C_ISR_STOPF) {
1536-
/* Disable interrupts */
1537-
if (stm32f7_i2c_is_slave_registered(i2c_dev))
1538-
mask = STM32F7_I2C_XFER_IRQ_MASK;
1551+
if (status & STM32F7_I2C_ISR_TCR) {
1552+
if (f7_msg->smbus)
1553+
stm32f7_i2c_smbus_reload(i2c_dev);
15391554
else
1540-
mask = STM32F7_I2C_ALL_IRQ_MASK;
1541-
stm32f7_i2c_disable_irq(i2c_dev, mask);
1542-
1543-
/* Clear STOP flag */
1544-
writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
1545-
1546-
if (i2c_dev->use_dma && !f7_msg->result) {
1547-
ret = IRQ_WAKE_THREAD;
1548-
} else {
1549-
i2c_dev->master_mode = false;
1550-
complete(&i2c_dev->complete);
1551-
}
1555+
stm32f7_i2c_reload(i2c_dev);
15521556
}
15531557

15541558
/* Transfer complete */
15551559
if (status & STM32F7_I2C_ISR_TC) {
1560+
/* Wait for dma transfer completion before sending next message */
1561+
if (i2c_dev->use_dma && !f7_msg->result) {
1562+
ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ);
1563+
if (!ret) {
1564+
dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__);
1565+
stm32f7_i2c_disable_dma_req(i2c_dev);
1566+
dmaengine_terminate_async(dma->chan_using);
1567+
f7_msg->result = -ETIMEDOUT;
1568+
}
1569+
}
15561570
if (f7_msg->stop) {
15571571
mask = STM32F7_I2C_CR2_STOP;
15581572
stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
1559-
} else if (i2c_dev->use_dma && !f7_msg->result) {
1560-
ret = IRQ_WAKE_THREAD;
15611573
} else if (f7_msg->smbus) {
15621574
stm32f7_i2c_smbus_rep_start(i2c_dev);
15631575
} else {
@@ -1567,55 +1579,26 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
15671579
}
15681580
}
15691581

1570-
if (status & STM32F7_I2C_ISR_TCR) {
1571-
if (f7_msg->smbus)
1572-
stm32f7_i2c_smbus_reload(i2c_dev);
1582+
/* STOP detection flag */
1583+
if (status & STM32F7_I2C_ISR_STOPF) {
1584+
/* Disable interrupts */
1585+
if (stm32f7_i2c_is_slave_registered(i2c_dev))
1586+
mask = STM32F7_I2C_XFER_IRQ_MASK;
15731587
else
1574-
stm32f7_i2c_reload(i2c_dev);
1575-
}
1576-
1577-
return ret;
1578-
}
1579-
1580-
static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
1581-
{
1582-
struct stm32f7_i2c_dev *i2c_dev = data;
1583-
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
1584-
struct stm32_i2c_dma *dma = i2c_dev->dma;
1585-
u32 status;
1586-
int ret;
1587-
1588-
/*
1589-
* Wait for dma transfer completion before sending next message or
1590-
* notity the end of xfer to the client
1591-
*/
1592-
ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ);
1593-
if (!ret) {
1594-
dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__);
1595-
stm32f7_i2c_disable_dma_req(i2c_dev);
1596-
dmaengine_terminate_async(dma->chan_using);
1597-
f7_msg->result = -ETIMEDOUT;
1598-
}
1588+
mask = STM32F7_I2C_ALL_IRQ_MASK;
1589+
stm32f7_i2c_disable_irq(i2c_dev, mask);
15991590

1600-
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
1591+
/* Clear STOP flag */
1592+
writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
16011593

1602-
if (status & STM32F7_I2C_ISR_TC) {
1603-
if (f7_msg->smbus) {
1604-
stm32f7_i2c_smbus_rep_start(i2c_dev);
1605-
} else {
1606-
i2c_dev->msg_id++;
1607-
i2c_dev->msg++;
1608-
stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg);
1609-
}
1610-
} else {
16111594
i2c_dev->master_mode = false;
16121595
complete(&i2c_dev->complete);
16131596
}
16141597

16151598
return IRQ_HANDLED;
16161599
}
16171600

1618-
static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
1601+
static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data)
16191602
{
16201603
struct stm32f7_i2c_dev *i2c_dev = data;
16211604
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
@@ -2202,8 +2185,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
22022185
if (ret)
22032186
return dev_err_probe(&pdev->dev, ret, "Failed to request irq event\n");
22042187

2205-
ret = devm_request_irq(&pdev->dev, irq_error, stm32f7_i2c_isr_error, 0,
2206-
pdev->name, i2c_dev);
2188+
ret = devm_request_threaded_irq(&pdev->dev, irq_error,
2189+
NULL,
2190+
stm32f7_i2c_isr_error_thread,
2191+
IRQF_ONESHOT,
2192+
pdev->name, i2c_dev);
22072193
if (ret)
22082194
return dev_err_probe(&pdev->dev, ret, "Failed to request irq error\n");
22092195

0 commit comments

Comments
 (0)