drivers: mcp23xxx: fix deadlock in interrupt callbacks
Interrupt callbacks may want to configure GPIO pins on the port expander, e.g. to change the polarity of a level interrupt. This would cause a deadlock because the callback handler would still be holding the lock. Signed-off-by: Armin Brauns <armin.brauns@embedded-solutions.at>
This commit is contained in:
parent
6c7cc1f683
commit
c094bd688a
1 changed files with 7 additions and 4 deletions
|
@ -408,7 +408,7 @@ static void mcp23xxx_work_handler(struct k_work *work)
|
|||
ret = read_port_regs(dev, REG_INTF, &intf);
|
||||
if (ret != 0) {
|
||||
LOG_ERR("Failed to read INTF");
|
||||
goto done;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!intf) {
|
||||
|
@ -416,7 +416,7 @@ static void mcp23xxx_work_handler(struct k_work *work)
|
|||
* handler had a chance to run
|
||||
*/
|
||||
LOG_ERR("Spurious interrupt");
|
||||
goto done;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint16_t intcap;
|
||||
|
@ -425,7 +425,7 @@ static void mcp23xxx_work_handler(struct k_work *work)
|
|||
ret = read_port_regs(dev, REG_INTCAP, &intcap);
|
||||
if (ret != 0) {
|
||||
LOG_ERR("Failed to read INTCAP");
|
||||
goto done;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* mcp23xxx does not support single-edge interrupts in hardware, filter them out manually */
|
||||
|
@ -434,8 +434,11 @@ static void mcp23xxx_work_handler(struct k_work *work)
|
|||
intf &= level_ints | (intcap & drv_data->rising_edge_ints) |
|
||||
(~intcap & drv_data->falling_edge_ints);
|
||||
|
||||
k_sem_give(&drv_data->lock);
|
||||
gpio_fire_callbacks(&drv_data->callbacks, dev, intf);
|
||||
done:
|
||||
return;
|
||||
|
||||
fail:
|
||||
k_sem_give(&drv_data->lock);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue