Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: DMUB Outbound Interrupt Process-X86

[Why]
dmub would notify x86 response time violation by GPINT_DATAOUT

[How]
1. Use GPINT_DATAOUT to trigger x86 interrupt
2. Register GPINT_DATAOUT interrupt handler.
3. Trigger ACR while GPINT_DATAOUT occurred.

Signed-off-by: Chun-Liang Chang <Chun-Liang.Chang@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Chun-Liang Chang and committed by
Alex Deucher
556a979d 1bc6c29f

+88 -3
+24
drivers/gpu/drm/amd/display/dc/core/dc_stat.c
··· 62 62 status = dmub_srv_stat_get_notification(dmub, notify); 63 63 ASSERT(status == DMUB_STATUS_OK); 64 64 } 65 + 66 + /** 67 + ***************************************************************************** 68 + * Function: dc_stat_get_dmub_dataout 69 + * 70 + * @brief 71 + * Calls dmub layer to retrieve dmub gpint dataout 72 + * 73 + * @param 74 + * [in] dc: dc structure 75 + * [in] dataout: dmub gpint dataout 76 + * 77 + * @return 78 + * None 79 + ***************************************************************************** 80 + */ 81 + void dc_stat_get_dmub_dataout(const struct dc *dc, uint32_t *dataout) 82 + { 83 + struct dmub_srv *dmub = dc->ctx->dmub_srv->dmub; 84 + enum dmub_status status; 85 + 86 + status = dmub_srv_get_gpint_dataout(dmub, dataout); 87 + ASSERT(status == DMUB_STATUS_OK); 88 + }
+1
drivers/gpu/drm/amd/display/dc/dc_stat.h
··· 38 38 #include "dmub/dmub_srv.h" 39 39 40 40 void dc_stat_get_dmub_notification(const struct dc *dc, struct dmub_notification *notify); 41 + void dc_stat_get_dmub_dataout(const struct dc *dc, uint32_t *dataout); 41 42 42 43 #endif /* _DC_STAT_H_ */
+1 -1
drivers/gpu/drm/amd/display/dc/irq_types.h
··· 152 152 DC_IRQ_SOURCE_DC6_VLINE1, 153 153 DC_IRQ_SOURCE_DMCUB_OUTBOX, 154 154 DC_IRQ_SOURCE_DMCUB_OUTBOX0, 155 - 155 + DC_IRQ_SOURCE_DMCUB_GENERAL_DATAOUT, 156 156 DAL_IRQ_SOURCES_NUMBER 157 157 }; 158 158
+18
drivers/gpu/drm/amd/display/dmub/dmub_srv.h
··· 352 352 353 353 uint32_t (*get_gpint_response)(struct dmub_srv *dmub); 354 354 355 + uint32_t (*get_gpint_dataout)(struct dmub_srv *dmub); 356 + 355 357 void (*send_inbox0_cmd)(struct dmub_srv *dmub, union dmub_inbox0_data_register data); 356 358 uint32_t (*get_current_time)(struct dmub_srv *dmub); 357 359 ··· 677 675 */ 678 676 enum dmub_status dmub_srv_get_gpint_response(struct dmub_srv *dmub, 679 677 uint32_t *response); 678 + 679 + /** 680 + * dmub_srv_get_gpint_dataout() - Queries the GPINT DATAOUT. 681 + * @dmub: the dmub service 682 + * @dataout: the data for the GPINT DATAOUT 683 + * 684 + * Returns the response code for the last GPINT DATAOUT interrupt. 685 + * 686 + * Can be called after software initialization. 687 + * 688 + * Return: 689 + * DMUB_STATUS_OK - success 690 + * DMUB_STATUS_INVALID - unspecified error 691 + */ 692 + enum dmub_status dmub_srv_get_gpint_dataout(struct dmub_srv *dmub, 693 + uint32_t *dataout); 680 694 681 695 /** 682 696 * dmub_flush_buffer_mem() - Read back entire frame buffer region.
+15
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
··· 305 305 return REG_READ(DMCUB_SCRATCH7); 306 306 } 307 307 308 + uint32_t dmub_dcn31_get_gpint_dataout(struct dmub_srv *dmub) 309 + { 310 + uint32_t dataout = REG_READ(DMCUB_GPINT_DATAOUT); 311 + 312 + REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 0); 313 + 314 + REG_WRITE(DMCUB_GPINT_DATAOUT, 0); 315 + REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 1); 316 + REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 0); 317 + 318 + REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 1); 319 + 320 + return dataout; 321 + } 322 + 308 323 union dmub_fw_boot_status dmub_dcn31_get_fw_boot_status(struct dmub_srv *dmub) 309 324 { 310 325 union dmub_fw_boot_status status;
+8 -2
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
··· 114 114 DMUB_SR(DMCUB_TIMER_CURRENT) \ 115 115 DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \ 116 116 DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \ 117 - DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR) 117 + DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR) \ 118 + DMUB_SR(DMCUB_INTERRUPT_ENABLE) \ 119 + DMUB_SR(DMCUB_INTERRUPT_ACK) 118 120 119 121 #define DMUB_DCN31_FIELDS() \ 120 122 DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \ ··· 149 147 DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \ 150 148 DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \ 151 149 DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \ 152 - DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR) 150 + DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR) \ 151 + DMUB_SF(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN) \ 152 + DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK) 153 153 154 154 struct dmub_srv_dcn31_reg_offset { 155 155 #define DMUB_SR(reg) uint32_t reg; ··· 225 221 union dmub_gpint_data_register reg); 226 222 227 223 uint32_t dmub_dcn31_get_gpint_response(struct dmub_srv *dmub); 224 + 225 + uint32_t dmub_dcn31_get_gpint_dataout(struct dmub_srv *dmub); 228 226 229 227 void dmub_dcn31_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params); 230 228
+17
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
··· 224 224 funcs->set_gpint = dmub_dcn31_set_gpint; 225 225 funcs->is_gpint_acked = dmub_dcn31_is_gpint_acked; 226 226 funcs->get_gpint_response = dmub_dcn31_get_gpint_response; 227 + funcs->get_gpint_dataout = dmub_dcn31_get_gpint_dataout; 227 228 funcs->get_fw_status = dmub_dcn31_get_fw_boot_status; 228 229 funcs->enable_dmub_boot_options = dmub_dcn31_enable_dmub_boot_options; 229 230 funcs->skip_dmub_panel_power_sequence = dmub_dcn31_skip_dmub_panel_power_sequence; ··· 716 715 return DMUB_STATUS_INVALID; 717 716 718 717 *response = dmub->hw_funcs.get_gpint_response(dmub); 718 + 719 + return DMUB_STATUS_OK; 720 + } 721 + 722 + enum dmub_status dmub_srv_get_gpint_dataout(struct dmub_srv *dmub, 723 + uint32_t *dataout) 724 + { 725 + *dataout = 0; 726 + 727 + if (!dmub->sw_init) 728 + return DMUB_STATUS_INVALID; 729 + 730 + if (!dmub->hw_funcs.get_gpint_dataout) 731 + return DMUB_STATUS_INVALID; 732 + 733 + *dataout = dmub->hw_funcs.get_gpint_dataout(dmub); 719 734 720 735 return DMUB_STATUS_OK; 721 736 }
+4
drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h
··· 5971 5971 #define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT1_INT_EN__SHIFT 0xb 5972 5972 #define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT2_INT_EN__SHIFT 0xc 5973 5973 #define DMCUB_INTERRUPT_ENABLE__DMCUB_UNDEFINED_ADDRESS_FAULT_INT_EN__SHIFT 0xd 5974 + #define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT_IH_INT_EN__SHIFT 0x11 5974 5975 #define DMCUB_INTERRUPT_ENABLE__DMCUB_TIMER0_INT_EN_MASK 0x00000001L 5975 5976 #define DMCUB_INTERRUPT_ENABLE__DMCUB_TIMER1_INT_EN_MASK 0x00000002L 5976 5977 #define DMCUB_INTERRUPT_ENABLE__DMCUB_INBOX0_READY_INT_EN_MASK 0x00000004L ··· 5986 5985 #define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT1_INT_EN_MASK 0x00000800L 5987 5986 #define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT2_INT_EN_MASK 0x00001000L 5988 5987 #define DMCUB_INTERRUPT_ENABLE__DMCUB_UNDEFINED_ADDRESS_FAULT_INT_EN_MASK 0x00002000L 5988 + #define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT_IH_INT_EN_MASK 0x00020000L 5989 5989 //DMCUB_INTERRUPT_ACK 5990 5990 #define DMCUB_INTERRUPT_ACK__DMCUB_TIMER0_INT_ACK__SHIFT 0x0 5991 5991 #define DMCUB_INTERRUPT_ACK__DMCUB_TIMER1_INT_ACK__SHIFT 0x1 ··· 6002 6000 #define DMCUB_INTERRUPT_ACK__DMCUB_GPINT1_INT_ACK__SHIFT 0xb 6003 6001 #define DMCUB_INTERRUPT_ACK__DMCUB_GPINT2_INT_ACK__SHIFT 0xc 6004 6002 #define DMCUB_INTERRUPT_ACK__DMCUB_UNDEFINED_ADDRESS_FAULT_ACK__SHIFT 0xd 6003 + #define DMCUB_INTERRUPT_ACK__DMCUB_GPINT_IH_INT_ACK__SHIFT 0x11 6005 6004 #define DMCUB_INTERRUPT_ACK__DMCUB_TIMER0_INT_ACK_MASK 0x00000001L 6006 6005 #define DMCUB_INTERRUPT_ACK__DMCUB_TIMER1_INT_ACK_MASK 0x00000002L 6007 6006 #define DMCUB_INTERRUPT_ACK__DMCUB_INBOX0_READY_INT_ACK_MASK 0x00000004L ··· 6017 6014 #define DMCUB_INTERRUPT_ACK__DMCUB_GPINT1_INT_ACK_MASK 0x00000800L 6018 6015 #define DMCUB_INTERRUPT_ACK__DMCUB_GPINT2_INT_ACK_MASK 0x00001000L 6019 6016 #define DMCUB_INTERRUPT_ACK__DMCUB_UNDEFINED_ADDRESS_FAULT_ACK_MASK 0x00002000L 6017 + #define DMCUB_INTERRUPT_ACK__DMCUB_GPINT_IH_INT_ACK_MASK 0x00020000L 6020 6018 //DMCUB_INTERRUPT_STATUS 6021 6019 #define DMCUB_INTERRUPT_STATUS__DMCUB_TIMER0_INT_STAT__SHIFT 0x0 6022 6020 #define DMCUB_INTERRUPT_STATUS__DMCUB_TIMER1_INT_STAT__SHIFT 0x1