Message ID | 20201221101733.912938-2-npiggin@gmail.com |
---|---|
State | Accepted |
Headers | show |
Series | [1/3] libpdbg/p10chip: remove delay from special wakeup clearing | expand |
On Mon, 21 Dec 2020 at 10:18, Nicholas Piggin <npiggin@gmail.com> wrote: > > This adds support for stop, start, sreset. > > Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Joel Stanley <joel@jms.id.au> > --- > libpdbg/p10_fapi_targets.c | 20 -------- > libpdbg/p10chip.c | 101 +++++++++++++++++++++++++++++++++++++ > 2 files changed, 101 insertions(+), 20 deletions(-) > > diff --git a/libpdbg/p10_fapi_targets.c b/libpdbg/p10_fapi_targets.c > index 6023389..0f16735 100644 > --- a/libpdbg/p10_fapi_targets.c > +++ b/libpdbg/p10_fapi_targets.c > @@ -488,25 +488,6 @@ static struct chiplet p10_chiplet = { > }; > DECLARE_HW_UNIT(p10_chiplet); > > -static int p10_thread_probe(struct pdbg_target *target) > -{ > - struct thread *thread = target_to_thread(target); > - > - thread->id = pdbg_target_index(target); > - > - return 0; > -} > - > -static struct thread p10_thread = { > - .target = { > - .name = "POWER10 Thread", > - .compatible = "ibm,power10-thread", > - .class = "thread", > - .probe = p10_thread_probe, > - }, > -}; > -DECLARE_HW_UNIT(p10_thread); > - > static uint64_t no_translate(struct pdbg_target *target, uint64_t addr) > { > /* No translation performed */ > @@ -540,6 +521,5 @@ static void register_p10_fapi_targets(void) > pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pauc_hw_unit); > pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pau_hw_unit); > pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_chiplet_hw_unit); > - pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_thread_hw_unit); > pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_fc_hw_unit); > } > diff --git a/libpdbg/p10chip.c b/libpdbg/p10chip.c > index f26e4ca..87d34e5 100644 > --- a/libpdbg/p10chip.c > +++ b/libpdbg/p10chip.c > @@ -22,8 +22,16 @@ > #include "chip.h" > #include "debug.h" > > +/* > + * NOTE! > + * All timeouts and scom procedures in general through the file should be kept > + * in synch with skiboot (e.g., core/direct-controls.c) as far as possible. > + * If you fix a bug here, fix it in skiboot, and vice versa. > + */ > + > #define P10_CORE_THREAD_STATE 0x28412 > #define P10_THREAD_INFO 0x28413 > +#define P10_DIRECT_CONTROL 0x28449 > #define P10_RAS_STATUS 0x28454 > > /* PCB Slave registers */ > @@ -31,6 +39,7 @@ > #define SPECIAL_WKUP_DONE PPC_BIT(1) > #define QME_SPWU_FSP 0xE8834 > > +#define RAS_STATUS_TIMEOUT 100 /* 100ms */ > #define SPECIAL_WKUP_TIMEOUT 100 /* 100ms */ > > static int thread_read(struct thread *thread, uint64_t addr, uint64_t *data) > @@ -40,6 +49,13 @@ static int thread_read(struct thread *thread, uint64_t addr, uint64_t *data) > return pib_read(core, addr, data); > } > > +static uint64_t thread_write(struct thread *thread, uint64_t addr, uint64_t data) > +{ > + struct pdbg_target *chip = pdbg_target_require_parent("core", &thread->target); > + > + return pib_write(chip, addr, data); > +} > + > struct thread_state p10_thread_state(struct thread *thread) > { > struct thread_state thread_state; > @@ -89,6 +105,90 @@ struct thread_state p10_thread_state(struct thread *thread) > return thread_state; > } > > +static int p10_thread_probe(struct pdbg_target *target) > +{ > + struct thread *thread = target_to_thread(target); > + > + thread->id = pdbg_target_index(target); > + thread->status = thread->state(thread); > + > + return 0; > +} > + > +static void p10_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 p10_thread_start(struct thread *thread) > +{ > + if (!(thread->status.quiesced)) > + return 1; > + > + if ((!(thread->status.active)) || > + (thread->status.sleep_state == PDBG_THREAD_STATE_STOP)) { > + /* Inactive or active and stopped: Clear Maint */ > + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(3 + 8*thread->id)); > + } else { > + /* Active and not stopped: Start */ > + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(6 + 8*thread->id)); > + } > + > + thread->status = thread->state(thread); > + > + return 0; > +} > + > +static int p10_thread_stop(struct thread *thread) > +{ > + int i = 0; > + > + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(7 + 8*thread->id)); > + while (!(thread->state(thread).quiesced)) { > + usleep(1000); > + if (i++ > RAS_STATUS_TIMEOUT) { > + PR_ERROR("Unable to quiesce thread\n"); > + break; > + } > + } > + thread->status = thread->state(thread); > + > + return 0; > +} > + > +static int p10_thread_sreset(struct thread *thread) > +{ > + /* Can only sreset if a thread is quiesced */ > + if (!(thread->status.quiesced)) > + return 1; > + > + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(4 + 8*thread->id)); > + > + thread->status = thread->state(thread); > + > + return 0; > +} > + > +static struct thread p10_thread = { > + .target = { > + .name = "POWER10 Thread", > + .compatible = "ibm,power10-thread", > + .class = "thread", > + .probe = p10_thread_probe, > + .release = p10_thread_release, > + }, > + .state = p10_thread_state, > + .start = p10_thread_start, > + .stop = p10_thread_stop, > + .sreset = p10_thread_sreset, > +}; > +DECLARE_HW_UNIT(p10_thread); > + > static int p10_core_probe(struct pdbg_target *target) > { > struct core *core = target_to_core(target); > @@ -190,5 +290,6 @@ DECLARE_HW_UNIT(p10_core); > __attribute__((constructor)) > static void register_p10chip(void) > { > + pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_thread_hw_unit); > pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_core_hw_unit); > } > -- > 2.23.0 > > -- > Pdbg mailing list > Pdbg@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/pdbg
diff --git a/libpdbg/p10_fapi_targets.c b/libpdbg/p10_fapi_targets.c index 6023389..0f16735 100644 --- a/libpdbg/p10_fapi_targets.c +++ b/libpdbg/p10_fapi_targets.c @@ -488,25 +488,6 @@ static struct chiplet p10_chiplet = { }; DECLARE_HW_UNIT(p10_chiplet); -static int p10_thread_probe(struct pdbg_target *target) -{ - struct thread *thread = target_to_thread(target); - - thread->id = pdbg_target_index(target); - - return 0; -} - -static struct thread p10_thread = { - .target = { - .name = "POWER10 Thread", - .compatible = "ibm,power10-thread", - .class = "thread", - .probe = p10_thread_probe, - }, -}; -DECLARE_HW_UNIT(p10_thread); - static uint64_t no_translate(struct pdbg_target *target, uint64_t addr) { /* No translation performed */ @@ -540,6 +521,5 @@ static void register_p10_fapi_targets(void) pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pauc_hw_unit); pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pau_hw_unit); pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_chiplet_hw_unit); - pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_thread_hw_unit); pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_fc_hw_unit); } diff --git a/libpdbg/p10chip.c b/libpdbg/p10chip.c index f26e4ca..87d34e5 100644 --- a/libpdbg/p10chip.c +++ b/libpdbg/p10chip.c @@ -22,8 +22,16 @@ #include "chip.h" #include "debug.h" +/* + * NOTE! + * All timeouts and scom procedures in general through the file should be kept + * in synch with skiboot (e.g., core/direct-controls.c) as far as possible. + * If you fix a bug here, fix it in skiboot, and vice versa. + */ + #define P10_CORE_THREAD_STATE 0x28412 #define P10_THREAD_INFO 0x28413 +#define P10_DIRECT_CONTROL 0x28449 #define P10_RAS_STATUS 0x28454 /* PCB Slave registers */ @@ -31,6 +39,7 @@ #define SPECIAL_WKUP_DONE PPC_BIT(1) #define QME_SPWU_FSP 0xE8834 +#define RAS_STATUS_TIMEOUT 100 /* 100ms */ #define SPECIAL_WKUP_TIMEOUT 100 /* 100ms */ static int thread_read(struct thread *thread, uint64_t addr, uint64_t *data) @@ -40,6 +49,13 @@ static int thread_read(struct thread *thread, uint64_t addr, uint64_t *data) return pib_read(core, addr, data); } +static uint64_t thread_write(struct thread *thread, uint64_t addr, uint64_t data) +{ + struct pdbg_target *chip = pdbg_target_require_parent("core", &thread->target); + + return pib_write(chip, addr, data); +} + struct thread_state p10_thread_state(struct thread *thread) { struct thread_state thread_state; @@ -89,6 +105,90 @@ struct thread_state p10_thread_state(struct thread *thread) return thread_state; } +static int p10_thread_probe(struct pdbg_target *target) +{ + struct thread *thread = target_to_thread(target); + + thread->id = pdbg_target_index(target); + thread->status = thread->state(thread); + + return 0; +} + +static void p10_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 p10_thread_start(struct thread *thread) +{ + if (!(thread->status.quiesced)) + return 1; + + if ((!(thread->status.active)) || + (thread->status.sleep_state == PDBG_THREAD_STATE_STOP)) { + /* Inactive or active and stopped: Clear Maint */ + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(3 + 8*thread->id)); + } else { + /* Active and not stopped: Start */ + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(6 + 8*thread->id)); + } + + thread->status = thread->state(thread); + + return 0; +} + +static int p10_thread_stop(struct thread *thread) +{ + int i = 0; + + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(7 + 8*thread->id)); + while (!(thread->state(thread).quiesced)) { + usleep(1000); + if (i++ > RAS_STATUS_TIMEOUT) { + PR_ERROR("Unable to quiesce thread\n"); + break; + } + } + thread->status = thread->state(thread); + + return 0; +} + +static int p10_thread_sreset(struct thread *thread) +{ + /* Can only sreset if a thread is quiesced */ + if (!(thread->status.quiesced)) + return 1; + + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(4 + 8*thread->id)); + + thread->status = thread->state(thread); + + return 0; +} + +static struct thread p10_thread = { + .target = { + .name = "POWER10 Thread", + .compatible = "ibm,power10-thread", + .class = "thread", + .probe = p10_thread_probe, + .release = p10_thread_release, + }, + .state = p10_thread_state, + .start = p10_thread_start, + .stop = p10_thread_stop, + .sreset = p10_thread_sreset, +}; +DECLARE_HW_UNIT(p10_thread); + static int p10_core_probe(struct pdbg_target *target) { struct core *core = target_to_core(target); @@ -190,5 +290,6 @@ DECLARE_HW_UNIT(p10_core); __attribute__((constructor)) static void register_p10chip(void) { + pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_thread_hw_unit); pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_core_hw_unit); }
This adds support for stop, start, sreset. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> --- libpdbg/p10_fapi_targets.c | 20 -------- libpdbg/p10chip.c | 101 +++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 20 deletions(-)