mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-01 14:44:12 +00:00
drm/amd/display: Use atomic types for ref_count
Current ref_count inc/dec is not guarded by locks which leads to a raced condition where two threads try to access the variable at the same time. In this case, both might act on the same cached value and inc/dec from the same value, rather than inc/dec by 2. Signed-off-by: Jerry Zuo <Jerry.Zuo@amd.com> Reviewed-by: Harry Wentland <Harry.Wentland@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
f81483c4cc
commit
e8cd26434d
8 changed files with 49 additions and 51 deletions
|
@ -454,7 +454,7 @@ static bool construct(struct core_dc *dc,
|
|||
goto val_ctx_fail;
|
||||
}
|
||||
|
||||
dc->current_context->ref_count++;
|
||||
atomic_inc(&dc->current_context->ref_count);
|
||||
|
||||
dc_ctx->cgs_device = init_params->cgs_device;
|
||||
dc_ctx->driver_context = init_params->driver;
|
||||
|
@ -704,7 +704,7 @@ struct validate_context *dc_get_validate_context(
|
|||
if (context == NULL)
|
||||
goto context_alloc_fail;
|
||||
|
||||
++context->ref_count;
|
||||
atomic_inc(&context->ref_count);
|
||||
|
||||
if (!is_validation_required(core_dc, set, set_count)) {
|
||||
dc_resource_validate_ctx_copy_construct(core_dc->current_context, context);
|
||||
|
@ -748,7 +748,7 @@ bool dc_validate_resources(
|
|||
if (context == NULL)
|
||||
goto context_alloc_fail;
|
||||
|
||||
++context->ref_count;
|
||||
atomic_inc(&context->ref_count);
|
||||
|
||||
result = core_dc->res_pool->funcs->validate_with_context(
|
||||
core_dc, set, set_count, context, NULL);
|
||||
|
@ -782,7 +782,7 @@ bool dc_validate_guaranteed(
|
|||
if (context == NULL)
|
||||
goto context_alloc_fail;
|
||||
|
||||
++context->ref_count;
|
||||
atomic_inc(&context->ref_count);
|
||||
|
||||
result = core_dc->res_pool->funcs->validate_guaranteed(
|
||||
core_dc, stream, context);
|
||||
|
@ -1090,7 +1090,7 @@ bool dc_commit_streams(
|
|||
if (context == NULL)
|
||||
goto context_alloc_fail;
|
||||
|
||||
++context->ref_count;
|
||||
atomic_inc(&context->ref_count);
|
||||
|
||||
result = core_dc->res_pool->funcs->validate_with_context(
|
||||
core_dc, set, stream_count, context, core_dc->current_context);
|
||||
|
@ -1203,16 +1203,16 @@ bool dc_commit_planes_to_stream(
|
|||
|
||||
void dc_retain_validate_context(struct validate_context *context)
|
||||
{
|
||||
ASSERT(context->ref_count > 0);
|
||||
++context->ref_count;
|
||||
ASSERT(atomic_read(&context->ref_count) > 0);
|
||||
atomic_inc(&context->ref_count);
|
||||
}
|
||||
|
||||
void dc_release_validate_context(struct validate_context *context)
|
||||
{
|
||||
ASSERT(context->ref_count > 0);
|
||||
--context->ref_count;
|
||||
ASSERT(atomic_read(&context->ref_count) > 0);
|
||||
atomic_dec(&context->ref_count);
|
||||
|
||||
if (context->ref_count == 0) {
|
||||
if (atomic_read(&context->ref_count) == 0) {
|
||||
dc_resource_validate_ctx_destruct(context);
|
||||
dm_free(context);
|
||||
}
|
||||
|
@ -1485,7 +1485,7 @@ void dc_update_planes_and_stream(struct dc *dc,
|
|||
if (context == NULL)
|
||||
goto context_alloc_fail;
|
||||
|
||||
++context->ref_count;
|
||||
atomic_inc(&context->ref_count);
|
||||
|
||||
dc_resource_validate_ctx_copy_construct(
|
||||
core_dc->current_context, context);
|
||||
|
@ -1800,7 +1800,7 @@ void dc_set_power_state(
|
|||
enum dc_acpi_cm_power_state power_state)
|
||||
{
|
||||
struct core_dc *core_dc = DC_TO_CORE(dc);
|
||||
int ref_count;
|
||||
atomic_t ref_count;
|
||||
|
||||
switch (power_state) {
|
||||
case DC_ACPI_CM_POWER_STATE_D0:
|
||||
|
|
|
@ -2238,7 +2238,7 @@ void dc_resource_validate_ctx_copy_construct(
|
|||
struct validate_context *dst_ctx)
|
||||
{
|
||||
int i, j;
|
||||
int ref_count = dst_ctx->ref_count;
|
||||
atomic_t ref_count = dst_ctx->ref_count;
|
||||
|
||||
*dst_ctx = *src_ctx;
|
||||
|
||||
|
|
|
@ -63,16 +63,16 @@ static bool construct(struct dc_sink *sink, const struct dc_sink_init_data *init
|
|||
|
||||
void dc_sink_retain(struct dc_sink *sink)
|
||||
{
|
||||
ASSERT(sink->ref_count > 0);
|
||||
++sink->ref_count;
|
||||
ASSERT(atomic_read(&sink->ref_count) > 0);
|
||||
atomic_inc(&sink->ref_count);
|
||||
}
|
||||
|
||||
void dc_sink_release(struct dc_sink *sink)
|
||||
{
|
||||
ASSERT(sink->ref_count > 0);
|
||||
--sink->ref_count;
|
||||
ASSERT(atomic_read(&sink->ref_count) > 0);
|
||||
atomic_dec(&sink->ref_count);
|
||||
|
||||
if (sink->ref_count == 0) {
|
||||
if (atomic_read(&sink->ref_count) == 0) {
|
||||
destruct(sink);
|
||||
dm_free(sink);
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params)
|
|||
if (false == construct(sink, init_params))
|
||||
goto construct_fail;
|
||||
|
||||
++sink->ref_count;
|
||||
atomic_inc(&sink->ref_count);
|
||||
|
||||
return sink;
|
||||
|
||||
|
|
|
@ -96,19 +96,17 @@ static void destruct(struct dc_stream_state *stream)
|
|||
|
||||
void dc_stream_retain(struct dc_stream_state *stream)
|
||||
{
|
||||
|
||||
ASSERT(stream->ref_count > 0);
|
||||
stream->ref_count++;
|
||||
ASSERT(atomic_read(&stream->ref_count) > 0);
|
||||
atomic_inc(&stream->ref_count);
|
||||
}
|
||||
|
||||
void dc_stream_release(struct dc_stream_state *stream)
|
||||
{
|
||||
|
||||
if (stream != NULL) {
|
||||
ASSERT(stream->ref_count > 0);
|
||||
stream->ref_count--;
|
||||
ASSERT(atomic_read(&stream->ref_count) > 0);
|
||||
atomic_dec(&stream->ref_count);
|
||||
|
||||
if (stream->ref_count == 0) {
|
||||
if (atomic_read(&stream->ref_count) == 0) {
|
||||
destruct(stream);
|
||||
dm_free(stream);
|
||||
}
|
||||
|
@ -131,7 +129,7 @@ struct dc_stream_state *dc_create_stream_for_sink(
|
|||
if (false == construct(stream, sink))
|
||||
goto construct_fail;
|
||||
|
||||
stream->ref_count++;
|
||||
atomic_inc(&stream->ref_count);
|
||||
|
||||
return stream;
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ struct dc_plane_state *dc_create_plane_state(const struct dc *dc)
|
|||
if (false == construct(core_dc->ctx, plane_state))
|
||||
goto construct_fail;
|
||||
|
||||
++plane_state->ref_count;
|
||||
atomic_inc(&plane_state->ref_count);
|
||||
|
||||
return plane_state;
|
||||
|
||||
|
@ -122,16 +122,16 @@ const struct dc_plane_status *dc_plane_get_status(
|
|||
|
||||
void dc_plane_state_retain(struct dc_plane_state *plane_state)
|
||||
{
|
||||
ASSERT(plane_state->ref_count > 0);
|
||||
++plane_state->ref_count;
|
||||
ASSERT(atomic_read(&plane_state->ref_count) > 0);
|
||||
atomic_inc(&plane_state->ref_count);
|
||||
}
|
||||
|
||||
void dc_plane_state_release(struct dc_plane_state *plane_state)
|
||||
{
|
||||
ASSERT(plane_state->ref_count > 0);
|
||||
--plane_state->ref_count;
|
||||
ASSERT(atomic_read(&plane_state->ref_count) > 0);
|
||||
atomic_dec(&plane_state->ref_count);
|
||||
|
||||
if (plane_state->ref_count == 0) {
|
||||
if (atomic_read(&plane_state->ref_count) == 0) {
|
||||
destruct(plane_state);
|
||||
dm_free(plane_state);
|
||||
}
|
||||
|
@ -139,16 +139,16 @@ void dc_plane_state_release(struct dc_plane_state *plane_state)
|
|||
|
||||
void dc_gamma_retain(struct dc_gamma *gamma)
|
||||
{
|
||||
ASSERT(gamma->ref_count > 0);
|
||||
++gamma->ref_count;
|
||||
ASSERT(atomic_read(&gamma->ref_count) > 0);
|
||||
atomic_inc(&gamma->ref_count);
|
||||
}
|
||||
|
||||
void dc_gamma_release(struct dc_gamma **gamma)
|
||||
{
|
||||
ASSERT((*gamma)->ref_count > 0);
|
||||
--(*gamma)->ref_count;
|
||||
ASSERT(atomic_read(&(*gamma)->ref_count) > 0);
|
||||
atomic_dec(&(*gamma)->ref_count);
|
||||
|
||||
if ((*gamma)->ref_count == 0)
|
||||
if (atomic_read(&(*gamma)->ref_count) == 0)
|
||||
dm_free((*gamma));
|
||||
|
||||
*gamma = NULL;
|
||||
|
@ -161,7 +161,7 @@ struct dc_gamma *dc_create_gamma()
|
|||
if (gamma == NULL)
|
||||
goto alloc_fail;
|
||||
|
||||
++gamma->ref_count;
|
||||
atomic_inc(&gamma->ref_count);
|
||||
|
||||
return gamma;
|
||||
|
||||
|
@ -171,16 +171,16 @@ struct dc_gamma *dc_create_gamma()
|
|||
|
||||
void dc_transfer_func_retain(struct dc_transfer_func *tf)
|
||||
{
|
||||
ASSERT(tf->ref_count > 0);
|
||||
++tf->ref_count;
|
||||
ASSERT(atomic_read(&tf->ref_count) > 0);
|
||||
atomic_inc(&tf->ref_count);
|
||||
}
|
||||
|
||||
void dc_transfer_func_release(struct dc_transfer_func *tf)
|
||||
{
|
||||
ASSERT(tf->ref_count > 0);
|
||||
--tf->ref_count;
|
||||
ASSERT(atomic_read(&tf->ref_count) > 0);
|
||||
atomic_dec(&tf->ref_count);
|
||||
|
||||
if (tf->ref_count == 0)
|
||||
if (atomic_read(&tf->ref_count) == 0)
|
||||
dm_free(tf);
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,7 @@ struct dc_transfer_func *dc_create_transfer_func()
|
|||
if (tf == NULL)
|
||||
goto alloc_fail;
|
||||
|
||||
++tf->ref_count;
|
||||
atomic_inc(&tf->ref_count);
|
||||
|
||||
return tf;
|
||||
|
||||
|
|
|
@ -295,7 +295,7 @@ struct dc_transfer_func {
|
|||
enum dc_transfer_func_type type;
|
||||
enum dc_transfer_func_predefined tf;
|
||||
struct dc_context *ctx;
|
||||
int ref_count;
|
||||
atomic_t ref_count;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -342,7 +342,7 @@ struct dc_plane_state {
|
|||
|
||||
/* private to dc_surface.c */
|
||||
enum dc_irq_source irq_source;
|
||||
int ref_count;
|
||||
atomic_t ref_count;
|
||||
};
|
||||
|
||||
struct dc_plane_info {
|
||||
|
@ -518,7 +518,7 @@ struct dc_stream_state {
|
|||
struct dc_stream_status status;
|
||||
|
||||
/* from stream struct */
|
||||
int ref_count;
|
||||
atomic_t ref_count;
|
||||
};
|
||||
|
||||
struct dc_stream_update {
|
||||
|
@ -902,7 +902,7 @@ struct dc_sink {
|
|||
struct dc_context *ctx;
|
||||
|
||||
/* private to dc_sink.c */
|
||||
int ref_count;
|
||||
atomic_t ref_count;
|
||||
};
|
||||
|
||||
void dc_sink_retain(struct dc_sink *sink);
|
||||
|
|
|
@ -433,7 +433,7 @@ struct dc_gamma {
|
|||
struct dc_context *ctx;
|
||||
|
||||
/* private to dc_surface.c */
|
||||
int ref_count;
|
||||
atomic_t ref_count;
|
||||
};
|
||||
|
||||
/* Used by both ipp amd opp functions*/
|
||||
|
|
|
@ -260,7 +260,7 @@ struct validate_context {
|
|||
struct dcn_bw_internal_vars dcn_bw_vars;
|
||||
#endif
|
||||
|
||||
int ref_count;
|
||||
atomic_t ref_count;
|
||||
};
|
||||
|
||||
#endif /* _CORE_TYPES_H_ */
|
||||
|
|
Loading…
Reference in a new issue