From 0df10a86fa7e2ea6c8269d77239f558aad0e550c Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Fri, 13 Nov 2015 14:55:55 +0800 Subject: MLK-11857 mxc IPUv3: PRE: Use spinlock to protect pre_list instead of mutex The pre_list can be accessed in an irq context. To avoid potential hang up issue, use spinlock to protect pre_list instead of mutex. Signed-off-by: Liu Ying (cherry picked from commit 16f552fb1fbd2626f81eacc7f2f7b2ce9b5ad11c) (cherry picked from commit 0d0c18b34b3fa889bbc22e10244c355c639ac694) --- drivers/mxc/ipu3/pre.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/mxc/ipu3/pre.c b/drivers/mxc/ipu3/pre.c index e625d272d60c..6df0dd5ce1d8 100644 --- a/drivers/mxc/ipu3/pre.c +++ b/drivers/mxc/ipu3/pre.c @@ -51,7 +51,7 @@ struct ipu_pre_data { }; static LIST_HEAD(pre_list); -static DEFINE_MUTEX(pre_list_lock); +static DEFINE_SPINLOCK(pre_list_lock); static inline void pre_write(struct ipu_pre_data *pre, u32 value, unsigned int offset) @@ -67,15 +67,16 @@ static inline u32 pre_read(struct ipu_pre_data *pre, unsigned offset) static struct ipu_pre_data *get_pre(unsigned int id) { struct ipu_pre_data *pre; + unsigned long lock_flags; - mutex_lock(&pre_list_lock); + spin_lock_irqsave(&pre_list_lock, lock_flags); list_for_each_entry(pre, &pre_list, list) { if (pre->id == id) { - mutex_unlock(&pre_list_lock); + spin_unlock_irqrestore(&pre_list_lock, lock_flags); return pre; } } - mutex_unlock(&pre_list_lock); + spin_unlock_irqrestore(&pre_list_lock, lock_flags); return NULL; } @@ -893,6 +894,7 @@ static int ipu_pre_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct ipu_pre_data *pre; struct resource *res; + unsigned long lock_flags; int id, irq, err; pre = devm_kzalloc(&pdev->dev, sizeof(*pre), GFP_KERNEL); @@ -935,9 +937,9 @@ static int ipu_pre_probe(struct platform_device *pdev) return -ENOMEM; } - mutex_lock(&pre_list_lock); + spin_lock_irqsave(&pre_list_lock, lock_flags); list_add_tail(&pre->list, &pre_list); - mutex_unlock(&pre_list_lock); + spin_unlock_irqrestore(&pre_list_lock, lock_flags); ipu_pre_alloc_double_buffer(pre->id, IPU_PRE_MAX_WIDTH * 8 * IPU_PRE_MAX_BPP); @@ -958,6 +960,7 @@ static int ipu_pre_probe(struct platform_device *pdev) static int ipu_pre_remove(struct platform_device *pdev) { struct ipu_pre_data *pre = platform_get_drvdata(pdev); + unsigned long lock_flags; if (pre->iram_pool && pre->double_buffer_base) { gen_pool_free(pre->iram_pool, @@ -965,9 +968,9 @@ static int ipu_pre_remove(struct platform_device *pdev) pre->double_buffer_size); } - mutex_lock(&pre_list_lock); + spin_lock_irqsave(&pre_list_lock, lock_flags); list_del(&pre->list); - mutex_unlock(&pre_list_lock); + spin_unlock_irqrestore(&pre_list_lock, lock_flags); return 0; } -- cgit v1.2.3