]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
comedi: jr3_pci: Fix synchronous deletion of timer
authorIan Abbott <abbotti@mev.co.uk>
Tue, 15 Apr 2025 12:39:01 +0000 (13:39 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 May 2025 05:44:39 +0000 (07:44 +0200)
commit 44d9b3f584c59a606b521e7274e658d5b866c699 upstream.

When `jr3_pci_detach()` is called during device removal, it calls
`timer_delete_sync()` to stop the timer, but the timer expiry function
always reschedules the timer, so the synchronization is ineffective.

Call `timer_shutdown_sync()` instead.  It does not matter that the timer
expiry function pointer is cleared, because the device is being removed.

Fixes: 07b509e6584a5 ("Staging: comedi: add jr3_pci driver")
Cc: stable <stable@kernel.org>
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Link: https://lore.kernel.org/r/20250415123901.13483-1-abbotti@mev.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/comedi/drivers/jr3_pci.c

index f963080dd61fb003c67ca68e760c5e759f268104..8ef13f5baf0720030645fbe412e0bd8e8e42b733 100644 (file)
@@ -88,6 +88,7 @@ struct jr3_pci_poll_delay {
 struct jr3_pci_dev_private {
        struct timer_list timer;
        struct comedi_device *dev;
+       bool timer_enable;
 };
 
 union jr3_pci_single_range {
@@ -597,10 +598,11 @@ static void jr3_pci_poll_dev(struct timer_list *t)
                                delay = sub_delay.max;
                }
        }
+       if (devpriv->timer_enable) {
+               devpriv->timer.expires = jiffies + msecs_to_jiffies(delay);
+               add_timer(&devpriv->timer);
+       }
        spin_unlock_irqrestore(&dev->spinlock, flags);
-
-       devpriv->timer.expires = jiffies + msecs_to_jiffies(delay);
-       add_timer(&devpriv->timer);
 }
 
 static struct jr3_pci_subdev_private *
@@ -749,6 +751,7 @@ static int jr3_pci_auto_attach(struct comedi_device *dev,
        devpriv->dev = dev;
        timer_setup(&devpriv->timer, jr3_pci_poll_dev, 0);
        devpriv->timer.expires = jiffies + msecs_to_jiffies(1000);
+       devpriv->timer_enable = true;
        add_timer(&devpriv->timer);
 
        return 0;
@@ -758,8 +761,12 @@ static void jr3_pci_detach(struct comedi_device *dev)
 {
        struct jr3_pci_dev_private *devpriv = dev->private;
 
-       if (devpriv)
-               del_timer_sync(&devpriv->timer);
+       if (devpriv) {
+               spin_lock_bh(&dev->spinlock);
+               devpriv->timer_enable = false;
+               spin_unlock_bh(&dev->spinlock);
+               timer_delete_sync(&devpriv->timer);
+       }
 
        comedi_pci_detach(dev);
 }