Merge "disp: msm: sde: flush commit thread queue during pm suspend"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

커밋
8bbc6f2698
@@ -747,6 +747,16 @@ int msm_atomic_commit(struct drm_device *dev,
|
|||||||
c->plane_mask |= (1 << drm_plane_index(plane));
|
c->plane_mask |= (1 << drm_plane_index(plane));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Protection for prepare_fence callback */
|
||||||
|
retry:
|
||||||
|
ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
|
||||||
|
state->acquire_ctx);
|
||||||
|
|
||||||
|
if (ret == -EDEADLK) {
|
||||||
|
drm_modeset_backoff(state->acquire_ctx);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for pending updates on any of the same crtc's and then
|
* Wait for pending updates on any of the same crtc's and then
|
||||||
* mark our set of crtc's as busy:
|
* mark our set of crtc's as busy:
|
||||||
|
@@ -3895,8 +3895,11 @@ int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Early out if simple ctl reset succeeded */
|
/*
|
||||||
if (i == sde_crtc->num_ctls)
|
* Early out if simple ctl reset succeeded or reset is
|
||||||
|
* being performed after timeout
|
||||||
|
*/
|
||||||
|
if (i == sde_crtc->num_ctls || crtc->state == old_state)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SDE_DEBUG("crtc%d: issuing hard reset\n", DRMID(crtc));
|
SDE_DEBUG("crtc%d: issuing hard reset\n", DRMID(crtc));
|
||||||
@@ -3999,6 +4002,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc,
|
|||||||
|
|
||||||
idle_pc_state = sde_crtc_get_property(cstate, CRTC_PROP_IDLE_PC_STATE);
|
idle_pc_state = sde_crtc_get_property(cstate, CRTC_PROP_IDLE_PC_STATE);
|
||||||
|
|
||||||
|
sde_crtc->kickoff_in_progress = true;
|
||||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||||
if (encoder->crtc != crtc)
|
if (encoder->crtc != crtc)
|
||||||
continue;
|
continue;
|
||||||
@@ -4060,6 +4064,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc,
|
|||||||
|
|
||||||
sde_encoder_kickoff(encoder, false, true);
|
sde_encoder_kickoff(encoder, false, true);
|
||||||
}
|
}
|
||||||
|
sde_crtc->kickoff_in_progress = false;
|
||||||
|
|
||||||
/* store the event after frame trigger */
|
/* store the event after frame trigger */
|
||||||
if (sde_crtc->event) {
|
if (sde_crtc->event) {
|
||||||
@@ -6565,6 +6570,9 @@ static int _sde_debugfs_fence_status_show(struct seq_file *s, void *data)
|
|||||||
dev = crtc->dev;
|
dev = crtc->dev;
|
||||||
cstate = to_sde_crtc_state(crtc->state);
|
cstate = to_sde_crtc_state(crtc->state);
|
||||||
|
|
||||||
|
if (!sde_crtc->kickoff_in_progress)
|
||||||
|
goto skip_input_fence;
|
||||||
|
|
||||||
/* Dump input fence info */
|
/* Dump input fence info */
|
||||||
seq_puts(s, "===Input fence===\n");
|
seq_puts(s, "===Input fence===\n");
|
||||||
drm_atomic_crtc_for_each_plane(plane, crtc) {
|
drm_atomic_crtc_for_each_plane(plane, crtc) {
|
||||||
@@ -6592,6 +6600,7 @@ static int _sde_debugfs_fence_status_show(struct seq_file *s, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skip_input_fence:
|
||||||
/* Dump release fence info */
|
/* Dump release fence info */
|
||||||
seq_puts(s, "\n");
|
seq_puts(s, "\n");
|
||||||
seq_puts(s, "===Release fence===\n");
|
seq_puts(s, "===Release fence===\n");
|
||||||
@@ -7097,6 +7106,7 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane)
|
|||||||
atomic_set(&sde_crtc->frame_pending, 0);
|
atomic_set(&sde_crtc->frame_pending, 0);
|
||||||
|
|
||||||
sde_crtc->enabled = false;
|
sde_crtc->enabled = false;
|
||||||
|
sde_crtc->kickoff_in_progress = false;
|
||||||
|
|
||||||
/* Below parameters are for fps calculation for sysfs node */
|
/* Below parameters are for fps calculation for sysfs node */
|
||||||
sde_crtc->fps_info.fps_periodic_duration = DEFAULT_FPS_PERIOD_1_SEC;
|
sde_crtc->fps_info.fps_periodic_duration = DEFAULT_FPS_PERIOD_1_SEC;
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include "sde_core_perf.h"
|
#include "sde_core_perf.h"
|
||||||
#include "sde_hw_ds.h"
|
#include "sde_hw_ds.h"
|
||||||
#include "sde_color_processing.h"
|
#include "sde_color_processing.h"
|
||||||
|
#include "sde_encoder.h"
|
||||||
|
|
||||||
#define SDE_CRTC_NAME_SIZE 12
|
#define SDE_CRTC_NAME_SIZE 12
|
||||||
|
|
||||||
@@ -285,6 +286,7 @@ struct sde_frame_data {
|
|||||||
* @ad_active : list containing ad properties that are active
|
* @ad_active : list containing ad properties that are active
|
||||||
* @crtc_lock : crtc lock around create, destroy and access.
|
* @crtc_lock : crtc lock around create, destroy and access.
|
||||||
* @frame_pending : Whether or not an update is pending
|
* @frame_pending : Whether or not an update is pending
|
||||||
|
* @kickoff_in_progress : boolean entry to check if kickoff is in progress
|
||||||
* @frame_events : static allocation of in-flight frame events
|
* @frame_events : static allocation of in-flight frame events
|
||||||
* @frame_event_list : available frame event list
|
* @frame_event_list : available frame event list
|
||||||
* @spin_lock : spin lock for transaction status, etc...
|
* @spin_lock : spin lock for transaction status, etc...
|
||||||
@@ -379,6 +381,7 @@ struct sde_crtc {
|
|||||||
struct list_head frame_event_list;
|
struct list_head frame_event_list;
|
||||||
spinlock_t spin_lock;
|
spinlock_t spin_lock;
|
||||||
spinlock_t fevent_spin_lock;
|
spinlock_t fevent_spin_lock;
|
||||||
|
bool kickoff_in_progress;
|
||||||
|
|
||||||
/* for handling internal event thread */
|
/* for handling internal event thread */
|
||||||
struct sde_crtc_event event_cache[SDE_CRTC_MAX_EVENT_COUNT];
|
struct sde_crtc_event event_cache[SDE_CRTC_MAX_EVENT_COUNT];
|
||||||
@@ -634,12 +637,15 @@ int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state,
|
|||||||
/**
|
/**
|
||||||
* sde_crtc_request_frame_reset - requests for next frame reset
|
* sde_crtc_request_frame_reset - requests for next frame reset
|
||||||
* @crtc: Pointer to drm crtc object
|
* @crtc: Pointer to drm crtc object
|
||||||
|
* @encoder: Pointer to drm encoder object
|
||||||
*/
|
*/
|
||||||
static inline int sde_crtc_request_frame_reset(struct drm_crtc *crtc)
|
static inline int sde_crtc_request_frame_reset(struct drm_crtc *crtc,
|
||||||
|
struct drm_encoder *encoder)
|
||||||
{
|
{
|
||||||
struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
|
struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
|
||||||
|
|
||||||
if (sde_crtc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START)
|
if (sde_crtc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START ||
|
||||||
|
!sde_encoder_is_dsi_display(encoder))
|
||||||
sde_crtc_reset_hw(crtc, crtc->state, false);
|
sde_crtc_reset_hw(crtc, crtc->state, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -2094,7 +2094,8 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc,
|
|||||||
sw_event, sde_enc->rc_state);
|
sw_event, sde_enc->rc_state);
|
||||||
SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, SDE_EVTLOG_ERROR);
|
SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, SDE_EVTLOG_ERROR);
|
||||||
goto end;
|
goto end;
|
||||||
} else if (sde_crtc_frame_pending(sde_enc->crtc)) {
|
} else if (sde_crtc_frame_pending(sde_enc->crtc) ||
|
||||||
|
sde_crtc->kickoff_in_progress) {
|
||||||
SDE_DEBUG_ENC(sde_enc, "skip idle entry");
|
SDE_DEBUG_ENC(sde_enc, "skip idle entry");
|
||||||
SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
|
SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
|
||||||
sde_crtc_frame_pending(sde_enc->crtc), SDE_EVTLOG_ERROR);
|
sde_crtc_frame_pending(sde_enc->crtc), SDE_EVTLOG_ERROR);
|
||||||
|
@@ -1415,20 +1415,27 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr(
|
|||||||
struct sde_encoder_phys_cmd *cmd_enc =
|
struct sde_encoder_phys_cmd *cmd_enc =
|
||||||
to_sde_encoder_phys_cmd(phys_enc);
|
to_sde_encoder_phys_cmd(phys_enc);
|
||||||
struct sde_encoder_wait_info wait_info = {0};
|
struct sde_encoder_wait_info wait_info = {0};
|
||||||
int ret;
|
struct sde_connector *c_conn;
|
||||||
bool frame_pending = true;
|
bool frame_pending = true;
|
||||||
struct sde_hw_ctl *ctl;
|
struct sde_hw_ctl *ctl;
|
||||||
unsigned long lock_flags;
|
unsigned long lock_flags;
|
||||||
|
int ret, timeout_ms;
|
||||||
|
|
||||||
if (!phys_enc || !phys_enc->hw_ctl) {
|
if (!phys_enc || !phys_enc->hw_ctl || !phys_enc->connector) {
|
||||||
SDE_ERROR("invalid argument(s)\n");
|
SDE_ERROR("invalid argument(s)\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
ctl = phys_enc->hw_ctl;
|
ctl = phys_enc->hw_ctl;
|
||||||
|
c_conn = to_sde_connector(phys_enc->connector);
|
||||||
|
timeout_ms = KICKOFF_TIMEOUT_MS;
|
||||||
|
|
||||||
|
if (c_conn->lp_mode == SDE_MODE_DPMS_LP1 ||
|
||||||
|
c_conn->lp_mode == SDE_MODE_DPMS_LP2)
|
||||||
|
timeout_ms = (KICKOFF_TIMEOUT_MS) * 2;
|
||||||
|
|
||||||
wait_info.wq = &phys_enc->pending_kickoff_wq;
|
wait_info.wq = &phys_enc->pending_kickoff_wq;
|
||||||
wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt;
|
wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt;
|
||||||
wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
|
wait_info.timeout_ms = timeout_ms;
|
||||||
|
|
||||||
/* slave encoder doesn't enable for ppsplit */
|
/* slave encoder doesn't enable for ppsplit */
|
||||||
if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
|
if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
|
||||||
|
@@ -839,6 +839,13 @@ static int sde_encoder_phys_wb_atomic_check(
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fmt->chroma_sample == SDE_CHROMA_H2V1 ||
|
||||||
|
fmt->chroma_sample == SDE_CHROMA_H1V2) {
|
||||||
|
SDE_ERROR("invalid chroma sample type in output format %x\n",
|
||||||
|
fmt->base.pixel_format);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (SDE_FORMAT_IS_UBWC(fmt) &&
|
if (SDE_FORMAT_IS_UBWC(fmt) &&
|
||||||
!(wb_cfg->features & BIT(SDE_WB_UBWC))) {
|
!(wb_cfg->features & BIT(SDE_WB_UBWC))) {
|
||||||
SDE_ERROR("invalid output format %x\n", fmt->base.pixel_format);
|
SDE_ERROR("invalid output format %x\n", fmt->base.pixel_format);
|
||||||
|
@@ -63,12 +63,12 @@ static int _dsc_calc_ob_max_addr(struct sde_hw_dsc *hw_dsc, int num_ss)
|
|||||||
|
|
||||||
idx = hw_dsc->idx;
|
idx = hw_dsc->idx;
|
||||||
|
|
||||||
if ((idx == DSC_0) || (idx == DSC_1)) {
|
if (!(hw_dsc->caps->features & BIT(SDE_DSC_NATIVE_422_EN))) {
|
||||||
if (num_ss == 1)
|
if (num_ss == 1)
|
||||||
return 2399;
|
return 2399;
|
||||||
else if (num_ss == 2)
|
else if (num_ss == 2)
|
||||||
return 1199;
|
return 1199;
|
||||||
} else if ((idx == DSC_2) || (idx == DSC_3)) {
|
} else {
|
||||||
if (num_ss == 1)
|
if (num_ss == 1)
|
||||||
return 1199;
|
return 1199;
|
||||||
else if (num_ss == 2)
|
else if (num_ss == 2)
|
||||||
|
@@ -1581,7 +1581,7 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms,
|
|||||||
ret = sde_encoder_wait_for_event(encoder, MSM_ENC_COMMIT_DONE);
|
ret = sde_encoder_wait_for_event(encoder, MSM_ENC_COMMIT_DONE);
|
||||||
if (ret && ret != -EWOULDBLOCK) {
|
if (ret && ret != -EWOULDBLOCK) {
|
||||||
SDE_ERROR("wait for commit done returned %d\n", ret);
|
SDE_ERROR("wait for commit done returned %d\n", ret);
|
||||||
sde_crtc_request_frame_reset(crtc);
|
sde_crtc_request_frame_reset(crtc, encoder);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1601,7 +1601,7 @@ static void sde_kms_prepare_fence(struct msm_kms *kms,
|
|||||||
{
|
{
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
struct drm_crtc_state *old_crtc_state;
|
struct drm_crtc_state *old_crtc_state;
|
||||||
int i, rc;
|
int i;
|
||||||
|
|
||||||
if (!kms || !old_state || !old_state->dev || !old_state->acquire_ctx) {
|
if (!kms || !old_state || !old_state->dev || !old_state->acquire_ctx) {
|
||||||
SDE_ERROR("invalid argument(s)\n");
|
SDE_ERROR("invalid argument(s)\n");
|
||||||
@@ -1609,15 +1609,6 @@ static void sde_kms_prepare_fence(struct msm_kms *kms,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDE_ATRACE_BEGIN("sde_kms_prepare_fence");
|
SDE_ATRACE_BEGIN("sde_kms_prepare_fence");
|
||||||
retry:
|
|
||||||
/* attempt to acquire ww mutex for connection */
|
|
||||||
rc = drm_modeset_lock(&old_state->dev->mode_config.connection_mutex,
|
|
||||||
old_state->acquire_ctx);
|
|
||||||
|
|
||||||
if (rc == -EDEADLK) {
|
|
||||||
drm_modeset_backoff(old_state->acquire_ctx);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* old_state actually contains updated crtc pointers */
|
/* old_state actually contains updated crtc pointers */
|
||||||
for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
|
for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
|
||||||
@@ -3565,6 +3556,11 @@ static void _sde_kms_pm_suspend_idle_helper(struct sde_kms *sde_kms,
|
|||||||
if (sde_encoder_in_clone_mode(conn->encoder))
|
if (sde_encoder_in_clone_mode(conn->encoder))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
crtc_id = drm_crtc_index(conn->state->crtc);
|
||||||
|
if (priv->disp_thread[crtc_id].thread)
|
||||||
|
kthread_flush_worker(
|
||||||
|
&priv->disp_thread[crtc_id].worker);
|
||||||
|
|
||||||
ret = sde_encoder_wait_for_event(conn->encoder,
|
ret = sde_encoder_wait_for_event(conn->encoder,
|
||||||
MSM_ENC_TX_COMPLETE);
|
MSM_ENC_TX_COMPLETE);
|
||||||
if (ret && ret != -EWOULDBLOCK) {
|
if (ret && ret != -EWOULDBLOCK) {
|
||||||
@@ -3572,7 +3568,6 @@ static void _sde_kms_pm_suspend_idle_helper(struct sde_kms *sde_kms,
|
|||||||
"[conn: %d] wait for commit done returned %d\n",
|
"[conn: %d] wait for commit done returned %d\n",
|
||||||
conn->base.id, ret);
|
conn->base.id, ret);
|
||||||
} else if (!ret) {
|
} else if (!ret) {
|
||||||
crtc_id = drm_crtc_index(conn->state->crtc);
|
|
||||||
if (priv->event_thread[crtc_id].thread)
|
if (priv->event_thread[crtc_id].thread)
|
||||||
kthread_flush_worker(
|
kthread_flush_worker(
|
||||||
&priv->event_thread[crtc_id].worker);
|
&priv->event_thread[crtc_id].worker);
|
||||||
|
Reference in New Issue
Block a user