Selaa lähdekoodia

msm: camera: reqmgr: Add protection for link reset

When crm close, call free link which free in_q.
The in_q ptr is null. It will result in null
in_q ptr deref when call notify trigger. So need
add spin lock to protect req data.

CRs-Fixed: 3488142
Change-Id: I25101f00e07bd56f1449085f2c6ce3ce3141adc3
Signed-off-by: Wang Kan <[email protected]>
Wang Kan 2 vuotta sitten
vanhempi
sitoutus
0f4492b985
2 muutettua tiedostoa jossa 27 lisäystä ja 13 poistoa
  1. 15 4
      drivers/cam_req_mgr/cam_req_mgr_core.c
  2. 12 9
      drivers/cam_req_mgr/cam_req_mgr_core.h

+ 15 - 4
drivers/cam_req_mgr/cam_req_mgr_core.c

@@ -53,6 +53,7 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
 {
 	int i = 0;
 
+	spin_lock_bh(&link->req.reset_link_spin_lock);
 	link->link_hdl = 0;
 	link->num_devs = 0;
 	link->max_delay = CAM_PIPELINE_DELAY_0;
@@ -90,15 +91,17 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
 	link->try_for_internal_recovery = false;
 	link->is_sending_req = false;
 	atomic_set(&link->eof_event_cnt, 0);
-	mutex_lock(&link->lock);
-	link->properties_mask = CAM_LINK_PROPERTY_NONE;
-	mutex_unlock(&link->lock);
 	link->cont_empty_slots = 0;
 	__cam_req_mgr_reset_apply_data(link);
 	__cam_req_mgr_reset_state_monitor_array(link);
 
 	for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; i++)
 		link->sync_link[i] = NULL;
+	spin_unlock_bh(&link->req.reset_link_spin_lock);
+
+	mutex_lock(&link->lock);
+	link->properties_mask = CAM_LINK_PROPERTY_NONE;
+	mutex_unlock(&link->lock);
 }
 
 void cam_req_mgr_handle_core_shutdown(void)
@@ -2901,7 +2904,6 @@ static void __cam_req_mgr_free_link(struct cam_req_mgr_core_link *link)
 {
 	ptrdiff_t i;
 	kfree(link->req.in_q);
-	link->req.in_q = NULL;
 	link->parent = NULL;
 	i = link - g_links;
 	CAM_DBG(CAM_CRM, "free link index %d", i);
@@ -4224,13 +4226,21 @@ static int cam_req_mgr_cb_notify_trigger(
 	trigger_id = trigger_data->trigger_id;
 	trigger = trigger_data->trigger;
 
+	spin_lock_bh(&link->req.reset_link_spin_lock);
 	in_q = link->req.in_q;
+	if (!in_q) {
+		CAM_DBG(CAM_CRM, "in_q ptr NULL, link_hdl %x", trigger_data->link_hdl);
+		spin_unlock_bh(&link->req.reset_link_spin_lock);
+		rc = -EINVAL;
+		goto end;
+	}
 
 	state.req_state = CAM_CRM_NOTIFY_TRIGGER;
 	state.req_id = in_q->slot[in_q->rd_idx].req_id;
 	state.dev_hdl = -1;
 	state.frame_id = trigger_data->frame_id;
 	__cam_req_mgr_update_state_monitor_array(link, &state);
+	spin_unlock_bh(&link->req.reset_link_spin_lock);
 
 	/*
 	 * Reduce the workq overhead when there is
@@ -5784,6 +5794,7 @@ int cam_req_mgr_core_device_init(void)
 		mutex_init(&g_links[i].lock);
 		spin_lock_init(&g_links[i].link_state_spin_lock);
 		spin_lock_init(&g_links[i].req.monitor_slock);
+		spin_lock_init(&g_links[i].req.reset_link_spin_lock);
 		atomic_set(&g_links[i].is_used, 0);
 		cam_req_mgr_core_link_reset(&g_links[i]);
 	}

+ 12 - 9
drivers/cam_req_mgr/cam_req_mgr_core.h

@@ -376,15 +376,17 @@ struct cam_req_mgr_state_monitor {
 
 /**
  * struct cam_req_mgr_req_data
- * @in_q             : Poiner to Input request queue
- * @l_tbl            : unique pd request tables.
- * @num_tbl          : how many unique pd value devices are present
- * @apply_data       : Holds information about request id for a request
- * @prev_apply_data  : Holds information about request id for a previous
- *                     applied request
- * @state_monitor    : used to track the request state in CRM
- * @next_state_idx   : indicates index to hold new request state
- * @lock             : mutex lock protecting request data ops.
+ * @in_q                  : Poiner to Input request queue
+ * @l_tbl                 : unique pd request tables.
+ * @num_tbl               : how many unique pd value devices are present
+ * @apply_data            : Holds information about request id for a request
+ * @prev_apply_data       : Holds information about request id for a previous
+ *                          applied request
+ * @state_monitor         : used to track the request state in CRM
+ * @next_state_idx        : indicates index to hold new request state
+ * @lock                  : mutex lock protecting request data ops.
+ * @monitor_slock         : spin lock protecting state mointor variables
+ * @reset_link_spin_lock  : spin lock protecting link data ops when reset link
  */
 struct cam_req_mgr_req_data {
 	struct cam_req_mgr_req_queue *in_q;
@@ -397,6 +399,7 @@ struct cam_req_mgr_req_data {
 	int32_t                       next_state_idx;
 	struct mutex                  lock;
 	spinlock_t                    monitor_slock;
+	spinlock_t                    reset_link_spin_lock;
 };
 
 /**