From: Ovidiu Bunea <[email protected]>

[why & how]
Allowing the DCHVM<->rIOMMU SDP port to disconnect during IPS1 cycling
can cause extra credits
to be released to rIOMMU. In turn, this will let the rIOMMU issue more
outstanding table walk requests
at once, overflowing the downstream request FIFO. This results in
dropped/orphaned
requests with no method of recovery. This typically manifests as an
invalidation hang error
in the main IOMMU.

As a workaround, dis-allow the SDP port from disconnecting from IPS1 exit
up until after
powerstatus=1. This ensures that rIOMMU does not have the chance to request
credits multiple
times during the powerstatus 0->1 transition.

Since x86 driver cannot access rIOMMU register space, send a command to DMU
to do it.

Reviewed-by: Nicholas Kazlauskas <[email protected]>
Signed-off-by: Ovidiu Bunea <[email protected]>
Signed-off-by: James Lin <[email protected]>
---
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c   | 18 ++++++++++++++++++
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h   | 12 ++++++++++++
 .../amd/display/dc/hubbub/dcn35/dcn35_hubbub.c |  7 +++++++
 3 files changed, 37 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c 
b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
index 01864fe816a3..4723e0974647 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -2527,3 +2527,21 @@ bool dc_dmub_srv_panel_polarity_get_polarity(struct 
dc_dmub_srv *dc_dmub_srv, ui
 
        return ret;
 }
+
+void dc_dmub_srv_hubbub_set_riommu_pctrl(const struct dc_context *ctx, 
uint32_t value)
+{
+       union dmub_rb_cmd cmd;
+
+       if (!(ctx->dce_version == DCN_VERSION_4_2 || ctx->dce_version == 
DCN_VERSION_4_2B))
+               return;
+
+       memset(&cmd, 0, sizeof(cmd));
+
+       cmd.dc_bls_dchvm_init.header.type = DMUB_CMD__DC_BLS;
+       cmd.dc_bls_dchvm_init.header.sub_type = DMUB_CMD__DC_BLS_DCHVM_INIT;
+       cmd.dc_bls_dchvm_init.header.payload_bytes = sizeof(struct 
dmub_cmd_dc_bls_dchvm_init_data);
+
+       cmd.dc_bls_dchvm_init.data.riommu_pctrl_val = value;
+
+       dc_wake_and_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h 
b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
index ec5387aedf46..ab026847e38b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
@@ -451,4 +451,16 @@ void dc_dmub_srv_panel_polarity_reset(struct dc_dmub_srv 
*dc_dmub_srv, uint8_t p
  */
 bool dc_dmub_srv_panel_polarity_get_polarity(struct dc_dmub_srv *dc_dmub_srv, 
uint8_t panel_inst, int32_t *polarity);
 
+/**
+ * dc_dmub_srv_hubbub_set_riommu_pctrl() - Program the RIOMMU PCTRL register 
via DMCUB.
+ *
+ * The RIOMMU PCTRL register (SMN address 0x16B0A100) controls the SDP port
+ * disconnection hysteresis between rIOMMU & DCHVM. It is not accessible from
+ * x86, so the write is offloaded to DMCUB.
+ *
+ * @ctx: dc context
+ * @value: value to program into the register (e.g. 0x20)
+ */
+void dc_dmub_srv_hubbub_set_riommu_pctrl(const struct dc_context *ctx, 
uint32_t value);
+
 #endif /* _DMUB_DC_SRV_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c 
b/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c
index 5e5a7a74346d..53744b000f5d 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c
@@ -31,6 +31,7 @@
 #include "dcn35_hubbub.h"
 #include "dm_services.h"
 #include "reg_helper.h"
+#include "dc_dmub_srv.h"
 
 
 #define CTX \
@@ -580,7 +581,13 @@ void dcn35_dchvm_init(struct hubbub *hubbub)
 
                //Reflect the power status of DCHUBBUB
                REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1);
+               udelay(5);
+       }
+
+       // generically re-allow the DCHVM<->rIOMMU SDP port to disconnect after 
powerstatus=1
+       dc_dmub_srv_hubbub_set_riommu_pctrl(hubbub->ctx, 0x20);
 
+       if (riommu_active) {
                //Start rIOMMU prefetching
                REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1);
 
-- 
2.43.0

Reply via email to