From 9a356830f52acdf9d3bf34d8e722b2938e43e082 Mon Sep 17 00:00:00 2001 From: Wentong Wu Date: Tue, 19 Oct 2021 23:09:49 +0800 Subject: [PATCH] UBUNTU: SAUCE: ivsc: return error when device not ready BugLink: https://bugs.launchpad.net/bugs/1955383 Return error when device not ready instead of blocking the calling thread. Signed-off-by: Wentong Wu (cherry picked from commit 06dec7c7fe2becaeaaab68e9bc386bf93fe80fa9 github.com/intel/ivsc-driver) Signed-off-by: You-Sheng Yang Acked-by: Andrea Righi Acked-by: Paolo Pisati --- drivers/misc/ivsc/intel_vsc.c | 104 +++++++++++++++++----------------- include/linux/vsc.h | 2 + 2 files changed, 54 insertions(+), 52 deletions(-) diff --git a/drivers/misc/ivsc/intel_vsc.c b/drivers/misc/ivsc/intel_vsc.c index 98bd701531b9..8beebac9f7fa 100644 --- a/drivers/misc/ivsc/intel_vsc.c +++ b/drivers/misc/ivsc/intel_vsc.c @@ -4,48 +4,41 @@ #include #include #include +#include #include -#include #include "intel_vsc.h" #define ACE_PRIVACY_ON 2 struct intel_vsc { + spinlock_t lock; struct mutex mutex; void *csi; struct vsc_csi_ops *csi_ops; uint16_t csi_registerred; - wait_queue_head_t csi_waitq; void *ace; struct vsc_ace_ops *ace_ops; uint16_t ace_registerred; - wait_queue_head_t ace_waitq; }; static struct intel_vsc vsc; -static int wait_component_ready(void) +static int check_component_ready(void) { - int ret; + int ret = -1; + unsigned long flags; - ret = wait_event_interruptible(vsc.ace_waitq, - vsc.ace_registerred); - if (ret < 0) { - pr_err("wait ace register failed\n"); - return ret; - } + spin_lock_irqsave(&vsc.lock, flags); - ret = wait_event_interruptible(vsc.csi_waitq, - vsc.csi_registerred); - if (ret < 0) { - pr_err("wait csi register failed\n"); - return ret; - } + if (vsc.ace_registerred && vsc.csi_registerred) + ret = 0; - return 0; + spin_unlock_irqrestore(&vsc.lock, flags); + + return ret; } static void update_camera_status(struct vsc_camera_status *status, @@ -63,17 +56,21 @@ static void update_camera_status(struct vsc_camera_status *status, int vsc_register_ace(void *ace, struct vsc_ace_ops *ops) { - if (ace && ops) + unsigned long flags; + + if (ace && ops) { if (ops->ipu_own_camera && ops->ace_own_camera) { - mutex_lock(&vsc.mutex); + spin_lock_irqsave(&vsc.lock, flags); + vsc.ace = ace; vsc.ace_ops = ops; vsc.ace_registerred = true; - mutex_unlock(&vsc.mutex); - wake_up_interruptible_all(&vsc.ace_waitq); + spin_unlock_irqrestore(&vsc.lock, flags); + return 0; } + } pr_err("register ace failed\n"); return -1; @@ -82,26 +79,34 @@ EXPORT_SYMBOL_GPL(vsc_register_ace); void vsc_unregister_ace(void) { - mutex_lock(&vsc.mutex); + unsigned long flags; + + spin_lock_irqsave(&vsc.lock, flags); + vsc.ace_registerred = false; - mutex_unlock(&vsc.mutex); + + spin_unlock_irqrestore(&vsc.lock, flags); } EXPORT_SYMBOL_GPL(vsc_unregister_ace); int vsc_register_csi(void *csi, struct vsc_csi_ops *ops) { - if (csi && ops) + unsigned long flags; + + if (csi && ops) { if (ops->set_privacy_callback && ops->set_owner && ops->set_mipi_conf) { - mutex_lock(&vsc.mutex); + spin_lock_irqsave(&vsc.lock, flags); + vsc.csi = csi; vsc.csi_ops = ops; vsc.csi_registerred = true; - mutex_unlock(&vsc.mutex); - wake_up_interruptible_all(&vsc.csi_waitq); + spin_unlock_irqrestore(&vsc.lock, flags); + return 0; } + } pr_err("register csi failed\n"); return -1; @@ -110,9 +115,13 @@ EXPORT_SYMBOL_GPL(vsc_register_csi); void vsc_unregister_csi(void) { - mutex_lock(&vsc.mutex); + unsigned long flags; + + spin_lock_irqsave(&vsc.lock, flags); + vsc.csi_registerred = false; - mutex_unlock(&vsc.mutex); + + spin_unlock_irqrestore(&vsc.lock, flags); } EXPORT_SYMBOL_GPL(vsc_unregister_csi); @@ -131,15 +140,14 @@ int vsc_acquire_camera_sensor(struct vsc_mipi_config *config, if (!config) return -EINVAL; - ret = wait_component_ready(); - if (ret) - return ret; + ret = check_component_ready(); + if (ret < 0) { + pr_info("intel vsc not ready\n"); + return -EAGAIN; + } mutex_lock(&vsc.mutex); - if (!vsc.csi_registerred || !vsc.ace_registerred) { - ret = -1; - goto err; - } + /* no need check component again here */ csi_ops = vsc.csi_ops; ace_ops = vsc.ace_ops; @@ -181,15 +189,14 @@ int vsc_release_camera_sensor(struct vsc_camera_status *status) struct vsc_csi_ops *csi_ops; struct vsc_ace_ops *ace_ops; - ret = wait_component_ready(); - if (ret) - return ret; + ret = check_component_ready(); + if (ret < 0) { + pr_info("intel vsc not ready\n"); + return -EAGAIN; + } mutex_lock(&vsc.mutex); - if (!vsc.csi_registerred || !vsc.ace_registerred) { - ret = -1; - goto err; - } + /* no need check component again here */ csi_ops = vsc.csi_ops; ace_ops = vsc.ace_ops; @@ -219,24 +226,17 @@ static int __init intel_vsc_init(void) { memset(&vsc, 0, sizeof(struct intel_vsc)); + spin_lock_init(&vsc.lock); mutex_init(&vsc.mutex); vsc.csi_registerred = false; vsc.ace_registerred = false; - init_waitqueue_head(&vsc.ace_waitq); - init_waitqueue_head(&vsc.csi_waitq); - return 0; } static void __exit intel_vsc_exit(void) { - if (wq_has_sleeper(&vsc.ace_waitq)) - wake_up_all(&vsc.ace_waitq); - - if (wq_has_sleeper(&vsc.csi_waitq)) - wake_up_all(&vsc.csi_waitq); } module_init(intel_vsc_init); diff --git a/include/linux/vsc.h b/include/linux/vsc.h index 0ce8ccb0bc52..8f8d40493dc6 100644 --- a/include/linux/vsc.h +++ b/include/linux/vsc.h @@ -59,6 +59,7 @@ typedef void (*vsc_privacy_callback_t)(void *handle, * @retval 0 If success * @retval -EIO IO error * @retval -EINVAL Invalid argument + * @retval -EAGAIN VSC device not ready * @retval negative values for other errors */ int vsc_acquire_camera_sensor(struct vsc_mipi_config *config, @@ -74,6 +75,7 @@ int vsc_acquire_camera_sensor(struct vsc_mipi_config *config, * @retval 0 If success * @retval -EIO IO error * @retval -EINVAL Invalid argument + * @retval -EAGAIN VSC device not ready * @retval negative values for other errors */ int vsc_release_camera_sensor(struct vsc_camera_status *status); -- 2.39.5