Skip to content

Commit 0b9dc43

Browse files
Alvin Leealexdeucher
Alvin Lee
authored andcommitted
drm/amd/display: Write flip addr to scratch reg for subvp
[Description] SubVP needs to "calculate" the earliest in use META address by using the current primary / meta addresses, but this leads to a race condition where FW and driver can read/write the address at the same time and intermittently produce inconsistent address offsets. To mitigate this issue without locking (too slow), save each surface flip addr into scratch registers and use this to keep track of the earliest in use META addres. Reviewed-by: Jun Lei <[email protected]> Acked-by: Wayne Lin <[email protected]> Signed-off-by: Alvin Lee <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent ec42478 commit 0b9dc43

File tree

11 files changed

+134
-1
lines changed

11 files changed

+134
-1
lines changed

drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c

+23
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include "hw_sequencer.h"
3030
#include "hw_sequencer_private.h"
3131
#include "basics/dc_common.h"
32+
#include "resource.h"
33+
#include "dc_dmub_srv.h"
3234

3335
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
3436

@@ -530,6 +532,15 @@ void hwss_build_fast_sequence(struct dc *dc,
530532
block_sequence[*num_steps].params.update_plane_addr_params.pipe_ctx = current_mpc_pipe;
531533
block_sequence[*num_steps].func = HUBP_UPDATE_PLANE_ADDR;
532534
(*num_steps)++;
535+
536+
if (resource_is_pipe_type(current_mpc_pipe, OTG_MASTER) &&
537+
current_mpc_pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
538+
block_sequence[*num_steps].params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv;
539+
block_sequence[*num_steps].params.subvp_save_surf_addr.addr = &current_mpc_pipe->plane_state->address;
540+
block_sequence[*num_steps].params.subvp_save_surf_addr.subvp_index = current_mpc_pipe->subvp_index;
541+
block_sequence[*num_steps].func = DMUB_SUBVP_SAVE_SURF_ADDR;
542+
(*num_steps)++;
543+
}
533544
}
534545

535546
if (hws->funcs.set_input_transfer_func && current_mpc_pipe->plane_state->update_flags.bits.gamma_change) {
@@ -697,6 +708,9 @@ void hwss_execute_sequence(struct dc *dc,
697708
case DMUB_SEND_DMCUB_CMD:
698709
hwss_send_dmcub_cmd(params);
699710
break;
711+
case DMUB_SUBVP_SAVE_SURF_ADDR:
712+
hwss_subvp_save_surf_addr(params);
713+
break;
700714
default:
701715
ASSERT(false);
702716
break;
@@ -789,6 +803,15 @@ void hwss_set_ocsc_default(union block_sequence_params *params)
789803
ocsc_mode);
790804
}
791805

806+
void hwss_subvp_save_surf_addr(union block_sequence_params *params)
807+
{
808+
struct dc_dmub_srv *dc_dmub_srv = params->subvp_save_surf_addr.dc_dmub_srv;
809+
const struct dc_plane_address *addr = params->subvp_save_surf_addr.addr;
810+
uint8_t subvp_index = params->subvp_save_surf_addr.subvp_index;
811+
812+
dc_dmub_srv_subvp_save_surf_addr(dc_dmub_srv, addr, subvp_index);
813+
}
814+
792815
void get_mclk_switch_visual_confirm_color(
793816
struct dc *dc,
794817
struct dc_state *context,

drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c

+5
Original file line numberDiff line numberDiff line change
@@ -1054,4 +1054,9 @@ void dc_dmub_srv_enable_dpia_trace(const struct dc *dc)
10541054
}
10551055

10561056
DC_LOG_DEBUG("Enabled DPIA trace\n");
1057+
}
1058+
1059+
void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, const struct dc_plane_address *addr, uint8_t subvp_index)
1060+
{
1061+
dmub_srv_subvp_save_surf_addr(dc_dmub_srv->dmub, addr, subvp_index);
10571062
}

drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h

+1
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,6 @@ void dc_send_update_cursor_info_to_dmu(struct pipe_ctx *pCtx, uint8_t pipe_idx);
8989
bool dc_dmub_check_min_version(struct dmub_srv *srv);
9090

9191
void dc_dmub_srv_enable_dpia_trace(const struct dc *dc);
92+
void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, const struct dc_plane_address *addr, uint8_t subvp_index);
9293

9394
#endif /* _DMUB_DC_SRV_H_ */

drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c

+11-1
Original file line numberDiff line numberDiff line change
@@ -1679,8 +1679,18 @@ static void dcn20_update_dchubp_dpp(
16791679

16801680
if (pipe_ctx->update_flags.bits.enable ||
16811681
pipe_ctx->update_flags.bits.plane_changed ||
1682-
plane_state->update_flags.bits.addr_update)
1682+
plane_state->update_flags.bits.addr_update) {
1683+
if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) &&
1684+
pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN) {
1685+
union block_sequence_params params;
1686+
1687+
params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv;
1688+
params.subvp_save_surf_addr.addr = &pipe_ctx->plane_state->address;
1689+
params.subvp_save_surf_addr.subvp_index = pipe_ctx->subvp_index;
1690+
hwss_subvp_save_surf_addr(&params);
1691+
}
16831692
hws->funcs.update_plane_addr(dc, pipe_ctx);
1693+
}
16841694

16851695
if (pipe_ctx->update_flags.bits.enable)
16861696
hubp->funcs->set_blank(hubp, false);

drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c

+18
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,23 @@ static bool subvp_validate_static_schedulability(struct dc *dc,
11441144
return schedulable;
11451145
}
11461146

1147+
static void assign_subvp_index(struct dc *dc, struct dc_state *context)
1148+
{
1149+
int i;
1150+
int index = 0;
1151+
1152+
for (i = 0; i < dc->res_pool->pipe_count; i++) {
1153+
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1154+
1155+
if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) &&
1156+
pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN) {
1157+
pipe_ctx->subvp_index = index++;
1158+
} else {
1159+
pipe_ctx->subvp_index = 0;
1160+
}
1161+
}
1162+
}
1163+
11471164
static void dcn32_full_validate_bw_helper(struct dc *dc,
11481165
struct dc_state *context,
11491166
display_e2e_pipe_params_st *pipes,
@@ -1294,6 +1311,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
12941311
vba->VoltageLevel = *vlevel;
12951312
// Note: We can't apply the phantom pipes to hardware at this time. We have to wait
12961313
// until driver has acquired the DMCUB lock to do it safely.
1314+
assign_subvp_index(dc, context);
12971315
}
12981316
}
12991317
}

drivers/gpu/drm/amd/display/dc/inc/core_types.h

+2
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,8 @@ struct pipe_ctx {
408408
union pipe_update_flags update_flags;
409409
struct tg_color visual_confirm_color;
410410
bool has_vactive_margin;
411+
/* subvp_index: only valid if the pipe is a SUBVP_MAIN*/
412+
uint8_t subvp_index;
411413
};
412414

413415
/* Data used for dynamic link encoder assignment.

drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h

+10
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ struct set_ocsc_default_params {
134134
enum mpc_output_csc_mode ocsc_mode;
135135
};
136136

137+
struct subvp_save_surf_addr {
138+
struct dc_dmub_srv *dc_dmub_srv;
139+
const struct dc_plane_address *addr;
140+
uint8_t subvp_index;
141+
};
142+
137143
union block_sequence_params {
138144
struct update_plane_addr_params update_plane_addr_params;
139145
struct subvp_pipe_control_lock_fast_params subvp_pipe_control_lock_fast_params;
@@ -151,6 +157,7 @@ union block_sequence_params {
151157
struct power_on_mpc_mem_pwr_params power_on_mpc_mem_pwr_params;
152158
struct set_output_csc_params set_output_csc_params;
153159
struct set_ocsc_default_params set_ocsc_default_params;
160+
struct subvp_save_surf_addr subvp_save_surf_addr;
154161
};
155162

156163
enum block_sequence_func {
@@ -170,6 +177,7 @@ enum block_sequence_func {
170177
MPC_POWER_ON_MPC_MEM_PWR,
171178
MPC_SET_OUTPUT_CSC,
172179
MPC_SET_OCSC_DEFAULT,
180+
DMUB_SUBVP_SAVE_SURF_ADDR,
173181
};
174182

175183
struct block_sequence {
@@ -471,4 +479,6 @@ void hwss_set_output_csc(union block_sequence_params *params);
471479

472480
void hwss_set_ocsc_default(union block_sequence_params *params);
473481

482+
void hwss_subvp_save_surf_addr(union block_sequence_params *params);
483+
474484
#endif /* __DC_HW_SEQUENCER_H__ */

drivers/gpu/drm/amd/display/dmub/dmub_srv.h

+17
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@ struct dmub_srv_hw_funcs {
401401

402402
bool (*should_detect)(struct dmub_srv *dmub);
403403
void (*init_reg_offsets)(struct dmub_srv *dmub, struct dc_context *ctx);
404+
405+
void (*subvp_save_surf_addr)(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index);
404406
};
405407

406408
/**
@@ -835,6 +837,21 @@ enum dmub_status dmub_srv_wait_for_inbox0_ack(struct dmub_srv *dmub, uint32_t ti
835837
*/
836838
enum dmub_status dmub_srv_clear_inbox0_ack(struct dmub_srv *dmub);
837839

840+
/**
841+
* dmub_srv_subvp_save_surf_addr() - Save primary and meta address for subvp on each flip
842+
* @dmub: The dmub service
843+
* @addr: The surface address to be programmed on the current flip
844+
* @subvp_index: Index of subvp pipe, indicates which subvp pipe the address should be saved for
845+
*
846+
* Function to save the surface flip addr into scratch registers. This is to fix a race condition
847+
* between FW and driver reading / writing to the surface address at the same time. This is
848+
* required because there is no EARLIEST_IN_USE_META.
849+
*
850+
* Return:
851+
* void
852+
*/
853+
void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index);
854+
838855
#if defined(__cplusplus)
839856
}
840857
#endif

drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c

+30
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "dmub_reg.h"
2828
#include "dmub_dcn32.h"
2929
#include "dc/dc_types.h"
30+
#include "dc_hw_types.h"
3031

3132
#include "dcn/dcn_3_2_0_offset.h"
3233
#include "dcn/dcn_3_2_0_sh_mask.h"
@@ -506,3 +507,32 @@ uint32_t dmub_dcn32_read_inbox0_ack_register(struct dmub_srv *dmub)
506507
{
507508
return REG_READ(DMCUB_SCRATCH17);
508509
}
510+
511+
void dmub_dcn32_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index)
512+
{
513+
uint32_t index = 0;
514+
515+
if (subvp_index == 0) {
516+
index = REG_READ(DMCUB_SCRATCH15);
517+
if (index) {
518+
REG_WRITE(DMCUB_SCRATCH9, addr->grph.addr.low_part);
519+
REG_WRITE(DMCUB_SCRATCH11, addr->grph.meta_addr.low_part);
520+
} else {
521+
REG_WRITE(DMCUB_SCRATCH12, addr->grph.addr.low_part);
522+
REG_WRITE(DMCUB_SCRATCH13, addr->grph.meta_addr.low_part);
523+
}
524+
REG_WRITE(DMCUB_SCRATCH15, !index);
525+
} else if (subvp_index == 1) {
526+
index = REG_READ(DMCUB_SCRATCH23);
527+
if (index) {
528+
REG_WRITE(DMCUB_SCRATCH18, addr->grph.addr.low_part);
529+
REG_WRITE(DMCUB_SCRATCH19, addr->grph.meta_addr.low_part);
530+
} else {
531+
REG_WRITE(DMCUB_SCRATCH20, addr->grph.addr.low_part);
532+
REG_WRITE(DMCUB_SCRATCH22, addr->grph.meta_addr.low_part);
533+
}
534+
REG_WRITE(DMCUB_SCRATCH23, !index);
535+
} else {
536+
return;
537+
}
538+
}

drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h

+7
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ struct dmub_srv;
107107
DMUB_SR(DMCUB_SCRATCH15) \
108108
DMUB_SR(DMCUB_SCRATCH16) \
109109
DMUB_SR(DMCUB_SCRATCH17) \
110+
DMUB_SR(DMCUB_SCRATCH18) \
111+
DMUB_SR(DMCUB_SCRATCH19) \
112+
DMUB_SR(DMCUB_SCRATCH20) \
113+
DMUB_SR(DMCUB_SCRATCH21) \
114+
DMUB_SR(DMCUB_SCRATCH22) \
115+
DMUB_SR(DMCUB_SCRATCH23) \
110116
DMUB_SR(DMCUB_GPINT_DATAIN0) \
111117
DMUB_SR(DMCUB_GPINT_DATAIN1) \
112118
DMUB_SR(DMCUB_GPINT_DATAOUT) \
@@ -253,6 +259,7 @@ void dmub_dcn32_configure_dmub_in_system_memory(struct dmub_srv *dmub);
253259
void dmub_dcn32_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data);
254260
void dmub_dcn32_clear_inbox0_ack_register(struct dmub_srv *dmub);
255261
uint32_t dmub_dcn32_read_inbox0_ack_register(struct dmub_srv *dmub);
262+
void dmub_dcn32_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index);
256263

257264
void dmub_srv_dcn32_regs_init(struct dmub_srv *dmub, struct dc_context *ctx);
258265

drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c

+10
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
278278
funcs->send_inbox0_cmd = dmub_dcn32_send_inbox0_cmd;
279279
funcs->clear_inbox0_ack_register = dmub_dcn32_clear_inbox0_ack_register;
280280
funcs->read_inbox0_ack_register = dmub_dcn32_read_inbox0_ack_register;
281+
funcs->subvp_save_surf_addr = dmub_dcn32_save_surf_addr;
281282
funcs->reset = dmub_dcn32_reset;
282283
funcs->reset_release = dmub_dcn32_reset_release;
283284
funcs->backdoor_load = dmub_dcn32_backdoor_load;
@@ -985,3 +986,12 @@ enum dmub_status dmub_srv_send_inbox0_cmd(struct dmub_srv *dmub,
985986
dmub->hw_funcs.send_inbox0_cmd(dmub, data);
986987
return DMUB_STATUS_OK;
987988
}
989+
990+
void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index)
991+
{
992+
if (dmub->hw_funcs.subvp_save_surf_addr) {
993+
dmub->hw_funcs.subvp_save_surf_addr(dmub,
994+
addr,
995+
subvp_index);
996+
}
997+
}

0 commit comments

Comments
 (0)