/* * Unregister a cec device node * * This unregisters the passed device. Future open calls will be met with * errors. * * 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_adapter *adap) { struct cec_devnode *devnode = &adap->devnode; struct cec_fh *fh; mutex_lock(&devnode->lock); /* Check if devnode was never registered or already unregistered */ if (!devnode->registered || devnode->unregistered) { mutex_unlock(&devnode->lock); return; } list_for_each_entry(fh, &devnode->fhs, list) wake_up_interruptible(&fh->wait); devnode->registered = false; 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); }
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); #if IS_REACHABLE(CONFIG_RC_CORE) rc_free_device(adap->rc); #endif kfree(adap); }
static long cec_adap_s_phys_addr(struct cec_adapter *adap, struct cec_fh *fh, bool block, __u16 __user *parg) { u16 phys_addr; long err; if (!(adap->capabilities & CEC_CAP_PHYS_ADDR)) return -ENOTTY; if (copy_from_user(&phys_addr, parg, sizeof(phys_addr))) return -EFAULT; err = cec_phys_addr_validate(phys_addr, NULL, NULL); if (err) return err; mutex_lock(&adap->lock); if (cec_is_busy(adap, fh)) err = -EBUSY; else __cec_s_phys_addr(adap, phys_addr, block); mutex_unlock(&adap->lock); return err; }