6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eliav Farber farbere@amazon.com
[ Upstream commit 6bca1e955830808dc90e0506b2951b4256b81bbb ]
The interrupt handler in pps_gpio_probe() is registered after calling pps_register_source() using devm_request_irq(). However, in the corresponding remove function, pps_unregister_source() is called before the IRQ is freed, since devm-managed resources are released after the remove function completes.
This creates a potential race condition where an interrupt may occur after the PPS source is unregistered but before the handler is removed, possibly leading to a kernel panic.
To prevent this, switch from devm-managed IRQ registration to manual management by using request_irq() and calling free_irq() explicitly in the remove path before unregistering the PPS source. This ensures the interrupt handler is safely removed before deactivating the PPS source.
Signed-off-by: Eliav Farber farbere@amazon.com Link: https://lore.kernel.org/r/20250527053355.37185-1-farbere@amazon.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pps/clients/pps-gpio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c index 47d9891de368..935da68610c7 100644 --- a/drivers/pps/clients/pps-gpio.c +++ b/drivers/pps/clients/pps-gpio.c @@ -210,8 +210,8 @@ static int pps_gpio_probe(struct platform_device *pdev) }
/* register IRQ interrupt handler */ - ret = devm_request_irq(dev, data->irq, pps_gpio_irq_handler, - get_irqf_trigger_flags(data), data->info.name, data); + ret = request_irq(data->irq, pps_gpio_irq_handler, + get_irqf_trigger_flags(data), data->info.name, data); if (ret) { pps_unregister_source(data->pps); dev_err(dev, "failed to acquire IRQ %d\n", data->irq); @@ -228,6 +228,7 @@ static void pps_gpio_remove(struct platform_device *pdev) { struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
+ free_irq(data->irq, data); pps_unregister_source(data->pps); timer_delete_sync(&data->echo_timer); /* reset echo pin in any case */