diff options
| author | Rahul Batra <rbatra@us.ibm.com> | 2018-03-01 16:51:54 -0600 |
|---|---|---|
| committer | hostboot <hostboot@us.ibm.com> | 2018-03-22 14:04:36 -0500 |
| commit | 234774b58a2a1045e916697b13e1b5360c35c2fa (patch) | |
| tree | 4dfc02e01ecb626d61cf3dfa1f0ecc58aaec2e89 | |
| parent | ee98a058264d3d316ce8de7252e7e592fdcb5994 (diff) | |
| download | talos-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>
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"); } |

