media: cec: core: disable adapter in cec_devnode_unregister
authorHans Verkuil <hverkuil-cisco@xs4all.nl>
Thu, 20 Apr 2023 07:26:53 +0000 (08:26 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Jun 2023 09:12:35 +0000 (11:12 +0200)
[ Upstream commit fe4526d99e2e06b08bb80316c3a596ea6a807b75 ]

Explicitly disable the CEC adapter in cec_devnode_unregister()

Usually this does not really do anything important, but for drivers
that use the CEC pin framework this is needed to properly stop the
hrtimer. Without this a crash would happen when such a driver is
unloaded with rmmod.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/media/cec/core/cec-adap.c
drivers/media/cec/core/cec-core.c
drivers/media/cec/core/cec-priv.h

index 4f5ab3c..ac18707 100644 (file)
@@ -1582,7 +1582,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
  *
  * This function is called with adap->lock held.
  */
-static int cec_adap_enable(struct cec_adapter *adap)
+int cec_adap_enable(struct cec_adapter *adap)
 {
        bool enable;
        int ret = 0;
@@ -1592,6 +1592,9 @@ static int cec_adap_enable(struct cec_adapter *adap)
        if (adap->needs_hpd)
                enable = enable && adap->phys_addr != CEC_PHYS_ADDR_INVALID;
 
+       if (adap->devnode.unregistered)
+               enable = false;
+
        if (enable == adap->is_enabled)
                return 0;
 
index af358e9..7e153c5 100644 (file)
@@ -191,6 +191,8 @@ static void cec_devnode_unregister(struct cec_adapter *adap)
        mutex_lock(&adap->lock);
        __cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false);
        __cec_s_log_addrs(adap, NULL, false);
+       // Disable the adapter (since adap->devnode.unregistered is true)
+       cec_adap_enable(adap);
        mutex_unlock(&adap->lock);
 
        cdev_device_del(&devnode->cdev, &devnode->dev);
index b78df93..ed1f8c6 100644 (file)
@@ -47,6 +47,7 @@ int cec_monitor_pin_cnt_inc(struct cec_adapter *adap);
 void cec_monitor_pin_cnt_dec(struct cec_adapter *adap);
 int cec_adap_status(struct seq_file *file, void *priv);
 int cec_thread_func(void *_adap);
+int cec_adap_enable(struct cec_adapter *adap);
 void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
 int __cec_s_log_addrs(struct cec_adapter *adap,
                      struct cec_log_addrs *log_addrs, bool block);