From: Hans Verkuil Date: Wed, 22 Nov 2017 09:12:39 +0000 (-0500) Subject: media: cec: disable the hardware when unregistered X-Git-Tag: v5.15~9456^2~376 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c8959a39fd47189a1474a4e92ffa34763589d6b0;p=platform%2Fkernel%2Flinux-starfive.git media: cec: disable the hardware when unregistered When the device is being unregistered disable the hardware, don't wait until cec_delete_adapter is called as the hardware may have disappeared by then. This would be the case for hotplugable devices. Signed-off-by: Hans Verkuil Reported-by: Bård Eirik Winther Tested-by: Bård Eirik Winther Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c index 3eb4a06..37e4680 100644 --- a/drivers/media/cec/cec-api.c +++ b/drivers/media/cec/cec-api.c @@ -46,12 +46,11 @@ static inline struct cec_devnode *cec_devnode_data(struct file *filp) static unsigned int cec_poll(struct file *filp, struct poll_table_struct *poll) { - struct cec_devnode *devnode = cec_devnode_data(filp); struct cec_fh *fh = filp->private_data; struct cec_adapter *adap = fh->adap; unsigned int res = 0; - if (!devnode->registered) + if (!cec_is_registered(adap)) return POLLERR | POLLHUP; mutex_lock(&adap->lock); if (adap->is_configured && @@ -486,13 +485,12 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh, static long cec_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct cec_devnode *devnode = cec_devnode_data(filp); struct cec_fh *fh = filp->private_data; struct cec_adapter *adap = fh->adap; bool block = !(filp->f_flags & O_NONBLOCK); void __user *parg = (void __user *)arg; - if (!devnode->registered) + if (!cec_is_registered(adap)) return -ENODEV; switch (cmd) { @@ -626,9 +624,8 @@ static int cec_release(struct inode *inode, struct file *filp) mutex_lock(&devnode->lock); list_del(&fh->list); - if (list_empty(&devnode->fhs) && - !adap->needs_hpd && - adap->phys_addr == CEC_PHYS_ADDR_INVALID) { + if (cec_is_registered(adap) && list_empty(&devnode->fhs) && + !adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) { WARN_ON(adap->ops->adap_enable(adap, false)); } mutex_unlock(&devnode->lock); diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index 5870da6..b5845b4 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -160,8 +160,9 @@ clr_bit: * This function can safely be called if the device node has never been * registered or has already been unregistered. */ -static void cec_devnode_unregister(struct cec_devnode *devnode) +static void cec_devnode_unregister(struct cec_adapter *adap) { + struct cec_devnode *devnode = &adap->devnode; struct cec_fh *fh; mutex_lock(&devnode->lock); @@ -179,6 +180,11 @@ static void cec_devnode_unregister(struct cec_devnode *devnode) devnode->unregistered = true; mutex_unlock(&devnode->lock); + mutex_lock(&adap->lock); + __cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false); + __cec_s_log_addrs(adap, NULL, false); + mutex_unlock(&adap->lock); + cdev_device_del(&devnode->cdev, &devnode->dev); put_device(&devnode->dev); } @@ -192,7 +198,7 @@ static void cec_cec_notify(struct cec_adapter *adap, u16 pa) void cec_register_cec_notifier(struct cec_adapter *adap, struct cec_notifier *notifier) { - if (WARN_ON(!adap->devnode.registered)) + if (WARN_ON(!cec_is_registered(adap))) return; adap->notifier = notifier; @@ -373,7 +379,7 @@ void cec_unregister_adapter(struct cec_adapter *adap) if (adap->notifier) cec_notifier_unregister(adap->notifier); #endif - cec_devnode_unregister(&adap->devnode); + cec_devnode_unregister(adap); } EXPORT_SYMBOL_GPL(cec_unregister_adapter); @@ -381,9 +387,6 @@ void cec_delete_adapter(struct cec_adapter *adap) { if (IS_ERR_OR_NULL(adap)) return; - mutex_lock(&adap->lock); - __cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false); - mutex_unlock(&adap->lock); kthread_stop(adap->kthread); if (adap->kthread_config) kthread_stop(adap->kthread_config); diff --git a/include/media/cec.h b/include/media/cec.h index dd781e9..1c6a797 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -230,6 +230,18 @@ static inline bool cec_is_sink(const struct cec_adapter *adap) return adap->phys_addr == 0; } +/** + * cec_is_registered() - is the CEC adapter registered? + * + * @adap: the CEC adapter, may be NULL. + * + * Return: true if the adapter is registered, false otherwise. + */ +static inline bool cec_is_registered(const struct cec_adapter *adap) +{ + return adap && adap->devnode.registered; +} + #define cec_phys_addr_exp(pa) \ ((pa) >> 12), ((pa) >> 8) & 0xf, ((pa) >> 4) & 0xf, (pa) & 0xf