[Pdbg] [PATCH v2 4/7] libpdbg/p8chip.c: release special wakeups for P8

Nicholas Piggin npiggin at gmail.com
Tue Mar 12 12:49:17 AEDT 2019


This copies the special wakeup release logic from p9chip.c

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 libpdbg/p8chip.c | 67 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 58 insertions(+), 9 deletions(-)

diff --git a/libpdbg/p8chip.c b/libpdbg/p8chip.c
index b93e953..71e6569 100644
--- a/libpdbg/p8chip.c
+++ b/libpdbg/p8chip.c
@@ -163,16 +163,11 @@ static int assert_special_wakeup(struct core *chip)
 	return 0;
 }
 
-#if 0
-/* TODO: Work out when to do this. */
-static int deassert_special_wakeup(struct core *chip)
+static void deassert_special_wakeup(struct core *chip)
 {
 	/* Assert special wakeup to prevent low power states */
-	CHECK_ERR(pib_write(&chip->target, PMSPCWKUPFSP_REG, 0));
-
-	return 0;
+	pib_write(&chip->target, PMSPCWKUPFSP_REG, 0);
 }
-#endif
 
 static struct thread_state get_thread_status(struct thread *thread)
 {
@@ -318,6 +313,8 @@ static int p8_thread_stop(struct thread *thread)
 	val |= PPC_BIT(8) >> thread->id;
 	CHECK_ERR(pib_write(&chip->target, THREAD_ACTIVE_REG, val));
 
+	thread->status = get_thread_status(thread);
+
 	return 0;
 }
 
@@ -336,6 +333,8 @@ static int p8_thread_start(struct thread *thread)
 	val |= PPC_BIT(thread->id);
 	CHECK_ERR(pib_write(&chip->target, THREAD_ACTIVE_REG, val));
 
+	thread->status = get_thread_status(thread);
+
 	return 0;
 }
 
@@ -366,7 +365,7 @@ static int p8_ram_setup(struct thread *thread)
 			return 1;
 
 		tmp = target_to_thread(target);
-		if (!(get_thread_status(tmp).quiesced))
+		if (!tmp->status.quiesced)
 			return 1;
 	}
 
@@ -487,6 +486,16 @@ static int p8_thread_probe(struct pdbg_target *target)
 	return 0;
 }
 
+static void p8_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 p8_get_hid0(struct pdbg_target *chip, uint64_t *value)
 {
 	CHECK_ERR(pib_read(chip, HID0_REG, value));
@@ -534,6 +543,7 @@ static struct thread p8_thread = {
 		.compatible = "ibm,power8-thread",
 		.class = "thread",
 		.probe = p8_thread_probe,
+		.release = p8_thread_release,
 	},
 	.step = p8_thread_step,
 	.start = p8_thread_start,
@@ -562,16 +572,55 @@ static int p8_core_probe(struct pdbg_target *target)
 	if (!GETFIELD(PPC_BIT(0), value))
 		return -1;
 
-	assert_special_wakeup(core);
+	if (assert_special_wakeup(core))
+		return -1;
+
+	/* Child threads will set this to false if they are released while quiesced */
+	core->release_spwkup = true;
+
 	return 0;
 }
 
+static void p8_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;
+
+	deassert_special_wakeup(core);
+	usleep(10000);
+}
+
 static struct core p8_core = {
 	.target = {
 		.name = "POWER8 Core",
 		.compatible = "ibm,power8-core",
 		.class = "core",
 		.probe = p8_core_probe,
+		.release = p8_core_release,
 	},
 };
 DECLARE_HW_UNIT(p8_core);
-- 
2.20.1



More information about the Pdbg mailing list