Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c8959a39 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

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: default avatarHans Verkuil <hans.verkuil@cisco.com>
Reported-by: default avatarBård Eirik Winther <bwinther@cisco.com>
Tested-by: default avatarBård Eirik Winther <bwinther@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 15ae0be9
Loading
Loading
Loading
Loading
+4 −7
Original line number Diff line number Diff line
@@ -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);
+9 −6
Original line number Diff line number Diff line
@@ -160,8 +160,9 @@ static int __must_check cec_devnode_register(struct cec_devnode *devnode,
 * 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);
+12 −0
Original line number Diff line number Diff line
@@ -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