|
@@ -1424,20 +1424,20 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ mutex_lock(&session->lock);
|
|
|
/*
|
|
|
- * In case if the wq is scheduled while destroying session
|
|
|
- * the session mutex is already taken and will cause a
|
|
|
- * dead lock. To avoid further processing check link state
|
|
|
- * and exit.
|
|
|
+ * During session destroy/unlink the link state is updated and session
|
|
|
+ * mutex is released when flushing the workq. In case the wq is scheduled
|
|
|
+ * thereafter this API will then check the updated link state and exit
|
|
|
*/
|
|
|
spin_lock_bh(&link->link_state_spin_lock);
|
|
|
if (link->state == CAM_CRM_LINK_STATE_IDLE) {
|
|
|
spin_unlock_bh(&link->link_state_spin_lock);
|
|
|
+ mutex_unlock(&session->lock);
|
|
|
return -EPERM;
|
|
|
}
|
|
|
spin_unlock_bh(&link->link_state_spin_lock);
|
|
|
|
|
|
- mutex_lock(&session->lock);
|
|
|
in_q = link->req.in_q;
|
|
|
/*
|
|
|
* Check if new read index,
|
|
@@ -4460,13 +4460,17 @@ end:
|
|
|
/**
|
|
|
* __cam_req_mgr_unlink()
|
|
|
*
|
|
|
- * @brief : Unlink devices on a link structure from the session
|
|
|
- * @link : Pointer to the link structure
|
|
|
+ * @brief : Unlink devices on a link structure from the session
|
|
|
+ * This API is to be invoked with session mutex held
|
|
|
+ * @session: session of the link
|
|
|
+ * @link : Pointer to the link structure
|
|
|
*
|
|
|
* @return: 0 for success, negative for failure
|
|
|
*
|
|
|
*/
|
|
|
-static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link)
|
|
|
+static int __cam_req_mgr_unlink(
|
|
|
+ struct cam_req_mgr_core_session *session,
|
|
|
+ struct cam_req_mgr_core_link *link)
|
|
|
{
|
|
|
int rc;
|
|
|
|
|
@@ -4482,14 +4486,16 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link)
|
|
|
}
|
|
|
|
|
|
mutex_lock(&link->lock);
|
|
|
-
|
|
|
spin_lock_bh(&link->link_state_spin_lock);
|
|
|
/* Destroy timer of link */
|
|
|
crm_timer_exit(&link->watchdog);
|
|
|
spin_unlock_bh(&link->link_state_spin_lock);
|
|
|
+ /* Release session mutex for workq processing */
|
|
|
+ mutex_unlock(&session->lock);
|
|
|
/* Destroy workq of link */
|
|
|
cam_req_mgr_workq_destroy(&link->workq);
|
|
|
-
|
|
|
+ /* Acquire session mutex after workq flush */
|
|
|
+ mutex_lock(&session->lock);
|
|
|
/* Cleanup request tables and unlink devices */
|
|
|
__cam_req_mgr_destroy_link_info(link);
|
|
|
/* Free memory holding data of linked devs */
|
|
@@ -4531,6 +4537,7 @@ int cam_req_mgr_destroy_session(
|
|
|
goto end;
|
|
|
|
|
|
}
|
|
|
+
|
|
|
mutex_lock(&cam_session->lock);
|
|
|
if (cam_session->num_links) {
|
|
|
CAM_DBG(CAM_CRM, "destroy session %x num_active_links %d",
|
|
@@ -4546,7 +4553,7 @@ int cam_req_mgr_destroy_session(
|
|
|
link->link_hdl);
|
|
|
/* Ignore return value since session is going away */
|
|
|
link->is_shutdown = is_shutdown;
|
|
|
- __cam_req_mgr_unlink(link);
|
|
|
+ __cam_req_mgr_unlink(cam_session, link);
|
|
|
__cam_req_mgr_free_link(link);
|
|
|
}
|
|
|
}
|
|
@@ -4829,8 +4836,9 @@ int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info)
|
|
|
rc = -EINVAL;
|
|
|
goto done;
|
|
|
}
|
|
|
-
|
|
|
- rc = __cam_req_mgr_unlink(link);
|
|
|
+ mutex_lock(&cam_session->lock);
|
|
|
+ rc = __cam_req_mgr_unlink(cam_session, link);
|
|
|
+ mutex_unlock(&cam_session->lock);
|
|
|
|
|
|
/* Free curent link and put back into session's free pool of links */
|
|
|
__cam_req_mgr_unreserve_link(cam_session, link);
|