summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRahul Batra <rbatra@us.ibm.com>2018-03-01 16:51:54 -0600
committerhostboot <hostboot@us.ibm.com>2018-03-22 14:04:36 -0500
commit234774b58a2a1045e916697b13e1b5360c35c2fa (patch)
tree4dfc02e01ecb626d61cf3dfa1f0ecc58aaec2e89
parentee98a058264d3d316ce8de7252e7e592fdcb5994 (diff)
downloadtalos-hcode-234774b58a2a1045e916697b13e1b5360c35c2fa.tar.gz
talos-hcode-234774b58a2a1045e916697b13e1b5360c35c2fa.zip
PM: Fixes CME Registration Protocol Hang during PM_SUSPEND
Key_Cronus_Test=PM_REGRESS Change-Id: I64acf1e08f3e8544c020d50d5677fe7ef036ab46 CQ: SW419088 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/54934 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Tested-by: Cronus HW CI <cronushw-ci+hostboot@us.ibm.com> Reviewed-by: RANGANATHPRASAD G. BRAHMASAMUDRA <prasadbgr@in.ibm.com> Reviewed-by: Gregory S. Still <stillgs@us.ibm.com> Reviewed-by: Brian T. Vanderpool <vanderp@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
-rw-r--r--import/chips/p9/common/pmlib/include/pstate_pgpe_cme_api.h21
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c163
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c33
3 files changed, 147 insertions, 70 deletions
diff --git a/import/chips/p9/common/pmlib/include/pstate_pgpe_cme_api.h b/import/chips/p9/common/pmlib/include/pstate_pgpe_cme_api.h
index 7e1c0488..7a51f0a5 100644
--- a/import/chips/p9/common/pmlib/include/pstate_pgpe_cme_api.h
+++ b/import/chips/p9/common/pmlib/include/pstate_pgpe_cme_api.h
@@ -98,7 +98,8 @@ enum MESSAGE_ID_DB0
MSGID_DB0_STOP_PSTATE_BROADCAST = 4,
MSGID_DB0_CLIP_BROADCAST = 5,
MSGID_DB0_PMSR_UPDT = 6,
- MSGID_DB0_VALID_END = 6 //This is for error checking
+ MSGID_DB0_REGISTER_DONE = 7,
+ MSGID_DB0_VALID_END = 7 //This is for error checking
};
enum MESSAGE_ID_DB3
@@ -262,5 +263,23 @@ typedef union pgpe_db0_pmsr_updt
} fields;
} pgpe_db0_pmsr_updt_t;
+//
+//PGPE-CME Doorbell0(Pstate Abort)
+//
+typedef union pgpe_db0_pstate_start_abort
+{
+ uint64_t value;
+ struct
+ {
+#ifdef _BIG_ENDIAN
+ uint64_t msg_id : 8;
+ uint64_t reserved: 56;
+#else
+ uint64_t reserved: 56;
+ uint64_t msg_id : 8;
+#endif
+ } fields;
+} pgpe_db0_pstate_start_abort_t;
+
#endif //__PSTATE_PGPE_CME_API_H__
diff --git a/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c
index 955bd058..caa9e666 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c
@@ -436,71 +436,71 @@ void p9_cme_pstate_process_db0()
uint32_t cme_flags = in32(CME_LCL_FLAGS);
- //Ignore if Doorbell0 if DB0_PROCESSING_ENABLE=0. This bit is zero
- //upon CME boot. PGPE will set it right before sending Pstate Starts.
- //PGPE clears it before ACKing Stop Entry Notify(this CME is about to powered off)
- //back to SGPE
- if (in32(CME_LCL_SRTCH0) & BIT32(CME_SCRATCH_DB0_PROCESSING_ENABLE))
- {
- //Process DB0
- //Start Pstates and Pstates NOT enabled
- if((G_dbData.fields.cme_message_number0 == MSGID_DB0_START_PSTATE_BROADCAST) &&
- (!(cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED))))
- {
- //This will Clear EISR[DB0_C0/1] to prevent another DB0 interrupt
- //PGPE multicast Global Bcast/Clip Bcast DB0, and it's possible that
- //the DB0 interrupt was taken as a result of multicast operation, but
- //the value of DB0 read corresponds to Pstate Start. In such a case,
- //another DB0 interrupt can happen, and it appears as PGPE has sent
- //a second Pstate Start causing CME to ACK back with error and Halt
- p9_cme_pstate_db0_start();
- }
- //Global Actual Broadcast and Pstates enabled
- else if((G_dbData.fields.cme_message_number0 == MSGID_DB0_GLOBAL_ACTUAL_BROADCAST) ||
- (G_dbData.fields.cme_message_number0 == MSGID_DB0_DB3_GLOBAL_ACTUAL_BROADCAST))
- {
- //Process Global Bcast only if Pstates are enabled.
- //Otherwise, ignore. The reason is PGPE multicasts Global Bcast, and doorbell0
- //can be written while this CME is powered-off or or about to be powered-off.
- //For Pstate Start and Stop PGPE only unicasts.
- if (cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED))
- {
- p9_cme_pstate_db0_glb_bcast();
- }
- }
- //Stop Pstates and Pstates enabled
- else if((G_dbData.fields.cme_message_number0 == MSGID_DB0_STOP_PSTATE_BROADCAST) &&
- (cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED)))
- {
- p9_cme_pstate_db0_stop();
- }
- //Pmin or Pmax Update
- else if(G_dbData.fields.cme_message_number0 == MSGID_DB0_CLIP_BROADCAST)
+ //Process DB0
+ //Start Pstates and Pstates NOT enabled
+ if((G_dbData.fields.cme_message_number0 == MSGID_DB0_START_PSTATE_BROADCAST) &&
+ (!(cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED))))
+ {
+ //This will Clear EISR[DB0_C0/1] to prevent another DB0 interrupt
+ //PGPE multicast Global Bcast/Clip Bcast DB0, and it's possible that
+ //the DB0 interrupt was taken as a result of multicast operation, but
+ //the value of DB0 read corresponds to Pstate Start. In such a case,
+ //another DB0 interrupt can happen, and it appears as PGPE has sent
+ //a second Pstate Start causing CME to ACK back with error and Halt
+ p9_cme_pstate_db0_start();
+ }
+ //Global Actual Broadcast and Pstates enabled
+ else if((G_dbData.fields.cme_message_number0 == MSGID_DB0_GLOBAL_ACTUAL_BROADCAST) ||
+ (G_dbData.fields.cme_message_number0 == MSGID_DB0_DB3_GLOBAL_ACTUAL_BROADCAST))
+ {
+ //Process Global Bcast only if Pstates are enabled.
+ //Otherwise, ignore. The reason is PGPE multicasts Global Bcast, and doorbell0
+ //can be written while this CME is powered-off or or about to be powered-off.
+ //For Pstate Start and Stop PGPE only unicasts.
+ if (cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED))
{
- p9_cme_pstate_db0_clip_bcast();
+ p9_cme_pstate_db0_glb_bcast();
}
- else if(G_dbData.fields.cme_message_number0 == MSGID_DB0_PMSR_UPDT)
+ }
+ //Stop Pstates and Pstates enabled
+ else if((G_dbData.fields.cme_message_number0 == MSGID_DB0_STOP_PSTATE_BROADCAST) &&
+ (cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED)))
+ {
+ p9_cme_pstate_db0_stop();
+ }
+ //Pmin or Pmax Update
+ else if(G_dbData.fields.cme_message_number0 == MSGID_DB0_CLIP_BROADCAST)
+ {
+ p9_cme_pstate_db0_clip_bcast();
+ }
+ else if(G_dbData.fields.cme_message_number0 == MSGID_DB0_PMSR_UPDT)
+ {
+ p9_cme_pstate_db0_pmsr_updt();
+ }
+ else if(G_dbData.fields.cme_message_number0 == MSGID_DB0_REGISTER_DONE)
+ {
+ ppmPigData.value = 0;
+ ppmPigData.fields.req_intr_type = 4;
+ ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_PSTATE_PROTO_ACK;
+ send_pig_packet(ppmPigData.value, G_cme_pstate_record.firstGoodCoreMask);
+ }
+ //Otherwise, send an ERR ACK to PGPE and Halt
+ else
+ {
+ ppmPigData.value = 0;
+ ppmPigData.fields.req_intr_type = 4;
+ ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_ERROR;
+ send_pig_packet(ppmPigData.value, G_cme_pstate_record.firstGoodCoreMask);
+ PK_TRACE_INF("PSTATE: Bad DB0=0x%x", (uint8_t)G_dbData.fields.cme_message_number0);
+
+ if(G_dbData.fields.cme_message_number0 < MSGID_DB0_VALID_START ||
+ G_dbData.fields.cme_message_number0 > MSGID_DB0_VALID_END)
{
- p9_cme_pstate_db0_pmsr_updt();
+ PK_PANIC(CME_PSTATE_UNEXPECTED_DB0_MSGID);
}
- //Otherwise, send an ERR ACK to PGPE and Halt
else
{
- ppmPigData.value = 0;
- ppmPigData.fields.req_intr_type = 4;
- ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_ERROR;
- send_pig_packet(ppmPigData.value, G_cme_pstate_record.firstGoodCoreMask);
- PK_TRACE_INF("PSTATE: Bad DB0=0x%x", (uint8_t)G_dbData.fields.cme_message_number0);
-
- if(G_dbData.fields.cme_message_number0 < MSGID_DB0_VALID_START ||
- G_dbData.fields.cme_message_number0 > MSGID_DB0_VALID_END)
- {
- PK_PANIC(CME_PSTATE_UNEXPECTED_DB0_MSGID);
- }
- else
- {
- PK_PANIC(CME_PSTATE_INVALID_DB0_MSGID);
- }
+ PK_PANIC(CME_PSTATE_INVALID_DB0_MSGID);
}
}
@@ -541,8 +541,11 @@ inline void p9_cme_pstate_register()
PK_TRACE_INF("PSTATE: DB0 Processing is Enabled");
- //PGPE will send Pmin, Pmax and Pstate Start Doorbells
- //Pstate Start is the last DB0
+ //PGPE sends MSGID_DB0_REGISTER_DONE, if Pstates aren't active anymore.
+ //Otherwise, PGPE sends DB0 in the following order
+ //1. MSGID_DB0_CLIP_BROADCAST
+ //2. MSGID_DB0_CLIP_BROADCAST
+ //3. MSGID_DB0_START_PSTATE_BROADCAST
while(!done)
{
uint32_t db0_check = G_cme_pstate_record.firstGoodCoreMask << SHIFT64SH(37);
@@ -565,6 +568,15 @@ inline void p9_cme_pstate_register()
{
p9_cme_pstate_db0_clip_bcast();
}
+ //PGPE sends this if Pstates aren't active anymore
+ else if ((G_dbData.fields.cme_message_number0 == MSGID_DB0_REGISTER_DONE))
+ {
+ done = 1;
+ ppmPigData.value = 0;
+ ppmPigData.fields.req_intr_type = 4;
+ ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_PSTATE_PROTO_ACK;
+ send_pig_packet(ppmPigData.value, G_cme_pstate_record.firstGoodCoreMask);
+ }
}
}
@@ -576,15 +588,32 @@ inline void p9_cme_pstate_register()
if (cme_flags & BIT32(CME_FLAGS_WAIT_ON_PSTATE_START))
{
- //PGPE sends Pmin, Pmax, and Pstate start DB0, so
- //total of three
PK_TRACE_INF("PSTATE: Wait on Pstate Start");
- while(msgCnt != 3)
+ //PGPE sends MSGID_DB0_REGISTER_DONE, if Pstates aren't active anymore.
+ //Otherwise, PGPE sends DB0 in the following order
+ //1. MSGID_DB0_CLIP_BROADCAST
+ //2. MSGID_DB0_CLIP_BROADCAST
+ //3. MSGID_DB0_START_PSTATE_BROADCAST
+ while(!done)
{
- p9_cme_pstate_sibling_lock_and_intercme_protocol(1);
- msgCnt++;
- PK_TRACE_INF("PSTATE: Sib Register MsgCnt=%d", msgCnt);
+ if ((G_dbData.fields.cme_message_number0 == MSGID_DB0_REGISTER_DONE))
+ {
+ done = 1;
+ PK_TRACE_INF("PSTATE: Sib Register Got Pstate Register Done");
+ }
+ else
+ {
+ p9_cme_pstate_sibling_lock_and_intercme_protocol(1);
+ msgCnt++;
+
+ if (msgCnt == 3)
+ {
+ done = 1;
+ }
+
+ PK_TRACE_INF("PSTATE: Sib Register MsgCnt=%d", msgCnt);
+ }
}
}
}
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c
index ea11dd1b..2a13c6de 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c
@@ -909,8 +909,9 @@ void p9_pgpe_process_registration()
uint32_t q, c, oldActiveDB, oldActiveQuads, unicastCoresVector = 0, quadsRegisterProcess;
uint32_t quadAckExpect = 0;
uint64_t value;
- pgpe_db0_start_ps_bcast_t db0_glb_bcast;
- pgpe_db0_clip_bcast_t db0_clip_bcast;
+ pgpe_db0_start_ps_bcast_t db0_glb_bcast;
+ pgpe_db0_clip_bcast_t db0_clip_bcast;
+ pgpe_db0_pstate_start_abort_t db0_pstate_start_abort;
//Save it for global bcast sync in case GlobalPSTarget is higher in
//after doing auctions with just registered quads
@@ -1096,6 +1097,34 @@ void p9_pgpe_process_registration()
}
}
}
+ //Send REGISTER_DONE if Pstates aren't active anymore
+ else
+ {
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if(quadsRegisterProcess & QUAD_MASK(q))
+ {
+ //Give Quad Manager CME control of DPLL through inter-ppm
+ //SGPE sets up the DPLL_SEL bits before booting CME
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(QPPM_QPMMR_OR, q), BIT64(26));
+
+ for (c = FIRST_CORE_FROM_QUAD(q); c < LAST_CORE_FROM_QUAD(q); c++)
+ {
+ if (G_pgpe_pstate_record.activeDB & CORE_MASK(c))
+ {
+ unicastCoresVector |= CORE_MASK(c);
+ }
+ }
+
+ quadAckExpect |= QUAD_MASK(q);
+ }
+ }
+
+ db0_pstate_start_abort.value = 0;
+ db0_pstate_start_abort.fields.msg_id = MSGID_DB0_REGISTER_DONE;
+ p9_pgpe_send_db0(db0_pstate_start_abort.value, unicastCoresVector, PGPE_DB0_UNICAST, PGPE_DB0_ACK_WAIT_CME,
+ quadAckExpect);
+ }
PK_TRACE_DBG("PTH: Register Exit");
}
OpenPOWER on IntegriCloud