static long cec_adap_s_log_addrs(struct cec_adapter *adap, struct cec_fh *fh, bool block, struct cec_log_addrs __user *parg) { struct cec_log_addrs log_addrs; long err = -EBUSY; if (!(adap->capabilities & CEC_CAP_LOG_ADDRS)) return -ENOTTY; if (copy_from_user(&log_addrs, parg, sizeof(log_addrs))) return -EFAULT; log_addrs.flags &= CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK | CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU | CEC_LOG_ADDRS_FL_CDC_ONLY; mutex_lock(&adap->lock); if (!adap->is_configuring && (!log_addrs.num_log_addrs || !adap->is_configured) && !cec_is_busy(adap, fh)) { err = __cec_s_log_addrs(adap, &log_addrs, block); if (!err) log_addrs = adap->log_addrs; } mutex_unlock(&adap->lock); if (err) return err; if (copy_to_user(parg, &log_addrs, sizeof(log_addrs))) return -EFAULT; return 0; }
/* * 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); }