diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index be693f9ea3ff..b5f10a232b89 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include @@ -535,32 +535,40 @@ static void __cam_req_mgr_validate_crm_wd_timer( CAM_DBG(CAM_CRM, "rd_idx: %d idx: %d current_frame_timeout: %d ms", in_q->rd_idx, idx, current_frame_timeout); - - if ((next_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT) > - link->watchdog->expires) { - CAM_DBG(CAM_CRM, - "Modifying wd timer expiry from %d ms to %d ms", - link->watchdog->expires, - (next_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT)); - crm_timer_modify(link->watchdog, - next_frame_timeout + - CAM_REQ_MGR_WATCHDOG_TIMEOUT); - } else if (current_frame_timeout) { - CAM_DBG(CAM_CRM, - "Reset wd timer to current frame from %d ms to %d ms", - link->watchdog->expires, - (current_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT)); - crm_timer_modify(link->watchdog, - current_frame_timeout + - CAM_REQ_MGR_WATCHDOG_TIMEOUT); - } else if (link->watchdog->expires > - CAM_REQ_MGR_WATCHDOG_TIMEOUT) { - CAM_DBG(CAM_CRM, - "Reset wd timer to default from %d ms to %d ms", - link->watchdog->expires, CAM_REQ_MGR_WATCHDOG_TIMEOUT); - crm_timer_modify(link->watchdog, - CAM_REQ_MGR_WATCHDOG_TIMEOUT); + spin_lock_bh(&link->link_state_spin_lock); + if (link->watchdog) { + if ((next_frame_timeout + CAM_REQ_MGR_WATCHDOG_TIMEOUT) > + link->watchdog->expires) { + CAM_DBG(CAM_CRM, + "Modifying wd timer expiry from %d ms to %d ms", + link->watchdog->expires, + (next_frame_timeout + + CAM_REQ_MGR_WATCHDOG_TIMEOUT)); + crm_timer_modify(link->watchdog, + next_frame_timeout + + CAM_REQ_MGR_WATCHDOG_TIMEOUT); + } else if (current_frame_timeout) { + CAM_DBG(CAM_CRM, + "Reset wd timer to frame from %d ms to %d ms", + link->watchdog->expires, + (current_frame_timeout + + CAM_REQ_MGR_WATCHDOG_TIMEOUT)); + crm_timer_modify(link->watchdog, + current_frame_timeout + + CAM_REQ_MGR_WATCHDOG_TIMEOUT); + } else if (link->watchdog->expires > + CAM_REQ_MGR_WATCHDOG_TIMEOUT) { + CAM_DBG(CAM_CRM, + "Reset wd timer to default from %d ms to %d ms", + link->watchdog->expires, + CAM_REQ_MGR_WATCHDOG_TIMEOUT); + crm_timer_modify(link->watchdog, + CAM_REQ_MGR_WATCHDOG_TIMEOUT); + } + } else { + CAM_WARN(CAM_CRM, "Watchdog timer exited already"); } + spin_unlock_bh(&link->link_state_spin_lock); } /** @@ -1720,6 +1728,14 @@ static int __cam_req_mgr_process_sof_freeze(void *priv, void *data) link = (struct cam_req_mgr_core_link *)priv; session = (struct cam_req_mgr_core_session *)link->parent; + spin_lock_bh(&link->link_state_spin_lock); + if ((link->watchdog) && (link->watchdog->pause_timer)) { + CAM_INFO(CAM_CRM, "Watchdog Paused"); + spin_unlock_bh(&link->link_state_spin_lock); + return rc; + } + spin_unlock_bh(&link->link_state_spin_lock); + CAM_ERR(CAM_CRM, "SOF freeze for session %d link 0x%x", session->session_hdl, link->link_hdl); @@ -1764,9 +1780,6 @@ static void __cam_req_mgr_sof_freeze(struct timer_list *timer_data) link = (struct cam_req_mgr_core_link *)timer->parent; - if (link->watchdog->pause_timer) - return; - task = cam_req_mgr_workq_get_task(link->workq); if (!task) { CAM_ERR(CAM_CRM, "No empty task"); @@ -2783,11 +2796,9 @@ static int cam_req_mgr_cb_notify_timer( rc = -EPERM; goto end; } - spin_unlock_bh(&link->link_state_spin_lock); - - - if (!timer_data->state) + if ((link->watchdog) && (!timer_data->state)) link->watchdog->pause_timer = true; + spin_unlock_bh(&link->link_state_spin_lock); end: return rc; @@ -2895,7 +2906,7 @@ static int cam_req_mgr_cb_notify_trigger( goto end; } - if (link->watchdog->pause_timer) + if ((link->watchdog) && (link->watchdog->pause_timer)) link->watchdog->pause_timer = false; crm_timer_reset(link->watchdog); @@ -3182,14 +3193,15 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link) /* Destroy workq of link */ cam_req_mgr_workq_destroy(&link->workq); - + 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); /* Cleanup request tables and unlink devices */ __cam_req_mgr_destroy_link_info(link); - /* Free memory holding data of linked devs */ + __cam_req_mgr_destroy_subdev(link->l_dev); /* Destroy the link handle */ @@ -3817,6 +3829,9 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) mutex_lock(&link->lock); if (control->ops == CAM_REQ_MGR_LINK_ACTIVATE) { + spin_lock_bh(&link->link_state_spin_lock); + link->state = CAM_CRM_LINK_STATE_READY; + spin_unlock_bh(&link->link_state_spin_lock); /* Start SOF watchdog timer */ rc = crm_timer_init(&link->watchdog, CAM_REQ_MGR_WATCHDOG_TIMEOUT, link, @@ -3838,10 +3853,6 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) dev->ops->process_evt(&evt_data); } } else if (control->ops == CAM_REQ_MGR_LINK_DEACTIVATE) { - /* Destroy SOF watchdog timer */ - spin_lock_bh(&link->link_state_spin_lock); - crm_timer_exit(&link->watchdog); - spin_unlock_bh(&link->link_state_spin_lock); /* notify nodes */ for (j = 0; j < link->num_devs; j++) { dev = &link->l_dev[j]; @@ -3852,6 +3863,11 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) if (dev->ops && dev->ops->process_evt) dev->ops->process_evt(&evt_data); } + /* Destroy SOF watchdog timer */ + spin_lock_bh(&link->link_state_spin_lock); + link->state = CAM_CRM_LINK_STATE_IDLE; + crm_timer_exit(&link->watchdog); + spin_unlock_bh(&link->link_state_spin_lock); } else { CAM_ERR(CAM_CRM, "Invalid link control command"); rc = -EINVAL;