[Pdbg] [PATCH] libpdbg: Don't release special wakeup when threads are quiesced

Alistair Popple alistair at popple.id.au
Mon Aug 13 15:02:19 AEST 2018


Signed-off-by: Alistair Popple <alistair at popple.id.au>
---
 libpdbg/p9chip.c | 40 ++++++++++++++++++++++++++++++++++++++++
 libpdbg/target.h |  1 +
 2 files changed, 41 insertions(+)

diff --git a/libpdbg/p9chip.c b/libpdbg/p9chip.c
index 2585f11..189d80a 100644
--- a/libpdbg/p9chip.c
+++ b/libpdbg/p9chip.c
@@ -125,6 +125,15 @@ static int p9_thread_probe(struct pdbg_target *target)
 	return 0;
 }
 
+static void p9_thread_release(struct pdbg_target *target)
+{
+	struct core *core = target_to_core(pdbg_target_require_parent("core", target));
+	struct thread *thread = target_to_thread(target);
+
+	if (thread->status.quiesced)
+		/* This thread is still quiesced so don't release spwkup */
+		core->release_spwkup = false;}
+
 static int p9_thread_start(struct thread *thread)
 {
 	if (!(thread->status.quiesced))
@@ -392,6 +401,7 @@ static struct thread p9_thread = {
 		.compatible = "ibm,power9-thread",
 		.class = "thread",
 		.probe = p9_thread_probe,
+		.release = p9_thread_release,
 	},
 	.start = p9_thread_start,
 	.stop = p9_thread_stop,
@@ -472,6 +482,7 @@ static int p9_chiplet_getring(struct chiplet *chiplet, uint64_t ring_addr, int64
 
 static int p9_core_probe(struct pdbg_target *target)
 {
+	struct core *core = target_to_core(target);
 	int i = 0;
 	uint64_t value;
 
@@ -493,12 +504,41 @@ static int p9_core_probe(struct pdbg_target *target)
 		}
 	} while (!(value & SPECIAL_WKUP_DONE));
 
+	/* Child threads will set this to false if they are released while quiesced */
+	core->release_spwkup = true;
+
 	return 0;
 }
 
 static void p9_core_release(struct pdbg_target *target)
 {
+	struct pdbg_target *child;
+	struct core *core = target_to_core(target);
+	enum pdbg_target_status status;
+
 	usleep(1); /* enforce small delay before and after it is cleared */
+
+	/* Probe and release all threads to ensure release_spwkup is up to
+	 * date */
+	pdbg_for_each_target("thread", target, child) {
+		status = pdbg_target_status(child);
+
+		/* This thread has already been release so should have set
+		 * release_spwkup to false if it was quiesced, */
+		if (status == PDBG_TARGET_RELEASED)
+			continue;
+
+		status = pdbg_target_probe(child);
+		if (status != PDBG_TARGET_ENABLED)
+			continue;
+
+		/* Release the thread to ensure release_spwkup is updated. */
+		pdbg_target_release(child);
+	}
+
+	if (!core->release_spwkup)
+		return;
+
 	pib_write(target, PPM_SPWKUP_FSP, 0);
 	usleep(10000);
 }
diff --git a/libpdbg/target.h b/libpdbg/target.h
index 6c2fa17..9f055ac 100644
--- a/libpdbg/target.h
+++ b/libpdbg/target.h
@@ -131,6 +131,7 @@ struct fsi {
 
 struct core {
 	struct pdbg_target target;
+	bool release_spwkup;
 };
 #define target_to_core(x) container_of(x, struct core, target)
 
-- 
2.11.0



More information about the Pdbg mailing list