[PATCH umr 15/17] Add umr_sq_cmd_singlestep

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Allow single-stepping a wave that is selected by HW ID.

Signed-off-by: Nicolai Hähnle <nicolai.haehnle@xxxxxxx>
---
 src/lib/sq_cmd_halt_waves.c | 75 ++++++++++++++++++++++++++++++++-----
 src/umr.h                   |  1 +
 2 files changed, 67 insertions(+), 9 deletions(-)

diff --git a/src/lib/sq_cmd_halt_waves.c b/src/lib/sq_cmd_halt_waves.c
index 841b1d3..9a0ae69 100644
--- a/src/lib/sq_cmd_halt_waves.c
+++ b/src/lib/sq_cmd_halt_waves.c
@@ -17,45 +17,51 @@
  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
  *
  * Authors: Tom St Denis <tom.stdenis@xxxxxxx>
  *
  */
 #include "umr.h"
 
+static struct umr_reg *find_sq_cmd(struct umr_asic *asic)
+{
+	// SQ_CMD is not present on SI
+	if (asic->family == FAMILY_SI)
+		return 0;
+
+	struct umr_reg *reg = umr_find_reg_data_by_ip_by_instance(asic, "gfx", asic->options.vm_partition,
+						  asic->family >= FAMILY_GFX11 ? "regSQ_CMD" : "mmSQ_CMD");
+	if (!reg)
+		asic->err_msg("[BUG]: Cannot find SQ_CMD register in umr_sq_cmd_halt_waves()\n");
+	return reg;
+}
+
 /**
  * umr_sq_cmd_halt_waves - Attempt to halt or resume waves
  *
  * @mode:	Use UMR_SQ_CMD_HALT to halt waves and
  * 			UMR_SQ_CMD_RESUME to resume waves.
  */
 int umr_sq_cmd_halt_waves(struct umr_asic *asic, enum umr_sq_cmd_halt_resume mode)
 {
 	struct umr_reg *reg;
 	uint32_t value;
 	uint64_t addr;
 	struct {
 		uint32_t se, sh, instance, use_grbm;
 	} grbm;
 
-	// SQ_CMD is not present on SI
-	if (asic->family == FAMILY_SI)
-		return 0;
-
-	reg = umr_find_reg_data_by_ip_by_instance(asic, "gfx", asic->options.vm_partition,
-						  asic->family >= FAMILY_GFX11 ? "regSQ_CMD" : "mmSQ_CMD");
-	if (!reg) {
-		asic->err_msg("[BUG]: Cannot find SQ_CMD register in umr_sq_cmd_halt_waves()\n");
+	reg = find_sq_cmd(asic);
+	if (!reg)
 		return -1;
-	}
 
 	// compose value
 	if (asic->family == FAMILY_CIK) {
 		value = umr_bitslice_compose_value(asic, reg, "CMD", mode == UMR_SQ_CMD_HALT ? 1 : 2); // SETHALT
 	} else {
 		value = umr_bitslice_compose_value(asic, reg, "CMD", 1); // SETHALT
 		value |= umr_bitslice_compose_value(asic, reg, "DATA", mode == UMR_SQ_CMD_HALT ? 1 : 0);
 	}
 	value |= umr_bitslice_compose_value(asic, reg, "MODE", 1); // BROADCAST
 
@@ -76,10 +82,61 @@ int umr_sq_cmd_halt_waves(struct umr_asic *asic, enum umr_sq_cmd_halt_resume mod
 	asic->reg_funcs.write_reg(asic, addr, value, reg->type);
 
 	/* restore whatever the user had picked */
 	asic->options.use_bank           = grbm.use_grbm;
 	asic->options.bank.grbm.se       = grbm.se;
 	asic->options.bank.grbm.sh       = grbm.sh;
 	asic->options.bank.grbm.instance = grbm.instance;
 
 	return 0;
 }
+
+/**
+ * umr_sq_cmd_singlestep - Attempt to single-step a single wave
+ *
+ * The wave is assumed to be halted.
+ */
+int umr_sq_cmd_singlestep(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t wgp, uint32_t simd, uint32_t wave)
+{
+	struct umr_reg *reg;
+	uint32_t value;
+	uint64_t addr;
+	struct {
+		uint32_t se, sh, instance, use_grbm;
+	} grbm;
+
+	if (asic->family < FAMILY_NV)
+		return -1; // Only supported on gfx10+
+
+	reg = find_sq_cmd(asic);
+	if (!reg)
+		return -1;
+
+	// compose value
+	value = umr_bitslice_compose_value(asic, reg, "CMD", 8); // SINGLE_STEP
+	value |= umr_bitslice_compose_value(asic, reg, "MODE", 0); // single wave
+	value |= umr_bitslice_compose_value(asic, reg, "WAVE_ID", wave);
+
+	/* copy grbm options to restore later */
+	grbm.use_grbm = asic->options.use_bank;
+	grbm.se       = asic->options.bank.grbm.se;
+	grbm.sh       = asic->options.bank.grbm.sh;
+	grbm.instance = asic->options.bank.grbm.instance;
+
+	/* set GRBM banking options */
+	asic->options.use_bank           = 1;
+	asic->options.bank.grbm.se       = se;
+	asic->options.bank.grbm.sh       = sh;
+	asic->options.bank.grbm.instance = (wgp << 2) | simd;
+
+	// compose address
+	addr = reg->addr * 4;
+	asic->reg_funcs.write_reg(asic, addr, value, reg->type);
+
+	/* restore whatever the user had picked */
+	asic->options.use_bank           = grbm.use_grbm;
+	asic->options.bank.grbm.se       = grbm.se;
+	asic->options.bank.grbm.sh       = grbm.sh;
+	asic->options.bank.grbm.instance = grbm.instance;
+
+	return 0;
+}
diff --git a/src/umr.h b/src/umr.h
index 616b9cc..8981986 100644
--- a/src/umr.h
+++ b/src/umr.h
@@ -1466,20 +1466,21 @@ uint64_t umr_bitslice_compose_value_by_name_by_ip_by_instance(struct umr_asic *a
 
 // bank switching
 uint64_t umr_apply_bank_selection_address(struct umr_asic *asic);
 
 // select a GRBM_GFX_IDX
 int umr_grbm_select_index(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t instance);
 int umr_srbm_select_index(struct umr_asic *asic, uint32_t me, uint32_t pipe, uint32_t queue, uint32_t vmid);
 
 // halt/resume SQ waves
 int umr_sq_cmd_halt_waves(struct umr_asic *asic, enum umr_sq_cmd_halt_resume mode);
+int umr_sq_cmd_singlestep(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t wgp, uint32_t simd, uint32_t wave);
 
 /* IB/ring decoding/dumping/etc */
 enum umr_ring_type {
 	UMR_RING_PM4,
 	UMR_RING_PM4_LITE,
 	UMR_RING_SDMA,
 	UMR_RING_MES,
 
 	UMR_RING_GUESS,
 	UMR_RING_UNK=0xFF, // if unknown
-- 
2.40.0




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux