Browse Source

msm: camera: cci: Semaphore may sleep in spin lock

When we enable CONFIG_DEBUG_ATOMIC_SLEEP=y, the kernel will do
might_sleep check when we down a semaphore, if the might_sleep
found it is in atomic context, it will eventually call BUG() to
raise kernel panic because sleep is not permitted in atomic
context. What we do now is get a spink lock before down a
semaphore, this is possible to make might_sleep reise a
kernel panic because semaphore might sleep in spin lock. So now
change the spin lock to mutex lock to avoid this situation.

CRs-Fixed: 3269325
Change-Id: I37735dfa615ec7dfe0fc38d04688025badd255d5
Signed-off-by: mingpan <[email protected]>
mingpan 2 years ago
parent
commit
7fffed86a5

+ 10 - 10
drivers/cam_sensor_module/cam_cci/cam_cci_core.c

@@ -663,11 +663,11 @@ static int32_t cam_cci_set_clk_param(struct cci_device *cci_dev,
 	if (i2c_freq_mode == cci_dev->i2c_freq_mode[master]) {
 		CAM_DBG(CAM_CCI, "CCI%d_I2C_M%d, curr_freq: %d", cci_dev->soc_info.index, master,
 			i2c_freq_mode);
-		spin_lock(&cci_master->freq_cnt_lock);
+		mutex_lock(&cci_master->freq_cnt_lock);
 		if (cci_master->freq_ref_cnt == 0)
 			down(&cci_master->master_sem);
 		cci_master->freq_ref_cnt++;
-		spin_unlock(&cci_master->freq_cnt_lock);
+		mutex_unlock(&cci_master->freq_cnt_lock);
 		mutex_unlock(&cci_master->mutex);
 		return 0;
 	}
@@ -675,9 +675,9 @@ static int32_t cam_cci_set_clk_param(struct cci_device *cci_dev,
 		cci_dev->soc_info.index, master, cci_dev->i2c_freq_mode[master], i2c_freq_mode);
 	down(&cci_master->master_sem);
 
-	spin_lock(&cci_master->freq_cnt_lock);
+	mutex_lock(&cci_master->freq_cnt_lock);
 	cci_master->freq_ref_cnt++;
-	spin_unlock(&cci_master->freq_cnt_lock);
+	mutex_unlock(&cci_master->freq_cnt_lock);
 
 	clk_params = &cci_dev->cci_clk_params[i2c_freq_mode];
 
@@ -1273,10 +1273,10 @@ enable_irq:
 rel_mutex_q:
 	mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
 
-	spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
+	mutex_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
 	if (--cci_dev->cci_master_info[master].freq_ref_cnt == 0)
 		up(&cci_dev->cci_master_info[master].master_sem);
-	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
+	mutex_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
 	return rc;
 }
 
@@ -1496,10 +1496,10 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
 rel_mutex_q:
 	mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
 
-	spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
+	mutex_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
 	if (--cci_dev->cci_master_info[master].freq_ref_cnt == 0)
 		up(&cci_dev->cci_master_info[master].master_sem);
-	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
+	mutex_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
 	return rc;
 }
 
@@ -1559,10 +1559,10 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
 	}
 
 ERROR:
-	spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
+	mutex_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
 	if (--cci_dev->cci_master_info[master].freq_ref_cnt == 0)
 		up(&cci_dev->cci_master_info[master].master_sem);
-	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
+	mutex_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
 	return rc;
 }
 

+ 1 - 1
drivers/cam_sensor_module/cam_cci/cam_cci_dev.h

@@ -138,7 +138,7 @@ struct cam_cci_master_info {
 	atomic_t done_pending[NUM_QUEUES];
 	spinlock_t lock_q[NUM_QUEUES];
 	struct semaphore master_sem;
-	spinlock_t freq_cnt_lock;
+	struct mutex freq_cnt_lock;
 	uint16_t freq_ref_cnt;
 	bool is_initilized;
 };

+ 2 - 1
drivers/cam_sensor_module/cam_cci/cam_cci_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include "cam_cci_dev.h"
@@ -245,7 +246,7 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev)
 		new_cci_dev->cci_master_info[i].is_initilized = false;
 		mutex_init(&new_cci_dev->cci_master_info[i].mutex);
 		sema_init(&new_cci_dev->cci_master_info[i].master_sem, 1);
-		spin_lock_init(&new_cci_dev->cci_master_info[i].freq_cnt_lock);
+		mutex_init(&new_cci_dev->cci_master_info[i].freq_cnt_lock);
 		init_completion(
 			&new_cci_dev->cci_master_info[i].reset_complete);
 		init_completion(