summaryrefslogtreecommitdiffstats
path: root/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c
diff options
context:
space:
mode:
authorYue Du <daviddu@us.ibm.com>2017-01-22 00:02:26 -0600
committerJoshua Hunsberger <jahunsbe@us.ibm.com>2017-10-23 18:00:49 -0500
commitbed4c8cd7e1a9338f631426aeb3e19451b0bc641 (patch)
tree3959e6e1e4b11bc0e9d146c2fb1f95e3463d71aa /import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c
parentffa811767e629eb9a53f85d6c498ab1505fa8861 (diff)
downloadtalos-hcode-bed4c8cd7e1a9338f631426aeb3e19451b0bc641.tar.gz
talos-hcode-bed4c8cd7e1a9338f631426aeb3e19451b0bc641.zip
STOP: block wakeup (+ block entry since patch 15)
Change-Id: I6636b7f77842e9a5e07fffa0f908fb4d46e7d763 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35205 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: BRIAN D. VICTOR <brian.d.victor1@ibm.com> Reviewed-by: Brian T. Vanderpool <vanderp@us.ibm.com> Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
Diffstat (limited to 'import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c')
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c310
1 files changed, 256 insertions, 54 deletions
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c
index 15a4954f..56b703a1 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c
@@ -46,12 +46,12 @@ SgpeStopRecord G_sgpe_stop_record __attribute__((section (".dump_ptrs"))) =
{0, 0, 0, 0, 0, 0, 0}
},
// group vectors
- { {0, 0, 0, 0, 0},
+ {
+ {0, 0, 0, 0},
{0, 0, 0, 0},
- {0, 0, 0},
- {0, 0, 0},
- {0, 0, 0},
- {0, 0, 0}
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0}
},
// wof status
{0, 0, 0, 0},
@@ -59,6 +59,144 @@ SgpeStopRecord G_sgpe_stop_record __attribute__((section (".dump_ptrs"))) =
{{0, 0, 0}}
};
+
+
+void
+p9_sgpe_stop_suspend_msg_db1(uint32_t qloop, uint32_t msgid)
+{
+ uint32_t cstart = 0;
+ uint32_t cloop = 0;
+ uint32_t cmask = 0;
+ data64_t scom_data = {0};
+ ppm_pig_t pig = {0};
+
+ for(cstart = 0; cstart < CORES_PER_QUAD; cstart += 2)
+ {
+ for(cloop = cstart, cmask = BIT32(((qloop << 2) + cstart));
+ cloop < (cstart + CORES_PER_EX);
+ cloop++, cmask = cmask >> 1)
+ {
+ // find the first good core served by each active CME
+ if (G_sgpe_stop_record.group.core[VECTOR_CONFIG] & cmask)
+ {
+ break;
+ }
+ }
+
+ // For each quad that is not in STOP 11, send doorbeel
+ if ((G_sgpe_stop_record.group.quad[VECTOR_ACTIVE] & BIT32(qloop)) &&
+ (cloop != (cstart + CORES_PER_EX))) // if ex is partial good
+ {
+ scom_data.words.upper = msgid;
+ scom_data.words.lower = 0;
+ p9_dd1_db_unicast_wr(GPE_SCOM_ADDR_CORE(CPPM_CMEDB1,
+ ((qloop << 2) + cloop)), scom_data.value);
+ }
+ // otherwise send an ack pig on behalf of that quad(stop11 or partial bad) or ex (ex is partial bad)
+ else
+ {
+ if (cloop == (cstart + CORES_PER_EX))
+ {
+ cloop = cstart;
+ }
+
+ pig.fields.req_intr_payload = msgid >> 16;
+ pig.fields.req_intr_payload |= 0x080; // set bit 4 for ack package
+ pig.fields.req_intr_type = PIG_TYPE2;
+ GPE_PUTSCOM(GPE_SCOM_ADDR_CORE(PPM_PIG, ((qloop << 2) + cloop)), pig.value);
+ }
+ }
+}
+
+void
+p9_sgpe_stop_ipi_handler(void* arg, PkIrqId irq)
+{
+ PkMachineContext ctx;
+ uint32_t qloop = 0;
+ uint32_t action = 0;
+ uint32_t occflg = in32(OCB_OCCFLG) & BITS32(9, 4);
+ data64_t scom_data = {0};
+
+ PK_TRACE_DBG("IPI-IRQ: %d", irq);
+ // Clear ipi3_lo interrupt
+ out32(OCB_OISR1_CLR, BIT32(29));
+
+ // occflg[9]control + [11]exit/[12]entry(filter bit[10] here)
+ // bit[9] must be on to perform any operations below
+ // also verify we are doing at least one operation from entry/exit
+ // otherwise, even bit[9] is on, the requested operation is undefined
+ // thus cannot be performed(no error taking out when this happens)
+ if ((occflg & (~BIT32(10))) > BIT32(9))
+ {
+ // msg[5-7] << occflg[10]enable + [11]exit/[12]entry (filter bit[9] here)
+ // msg[5] : perform block/unblock operation (enable/disable ignore stop func)
+ // msg[6] : perform exit block/unblock operation
+ // msg[7] : perform entry block/unblock operation
+ action = ((occflg & (~BIT32(9))) << 5);
+
+ for (qloop = 0; qloop < MAX_QUADS; qloop++)
+ {
+ if (!(G_sgpe_stop_record.group.quad[VECTOR_CONFIG] & BIT32(qloop)))
+ {
+ continue;
+ }
+
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(QPPM_QCCR, qloop), scom_data.value);
+
+ // target quad is to participate block/unblock exit
+ if (scom_data.words.upper & BIT32(10))
+ {
+ action = action | BIT32(6);
+
+ if (action & BIT32(5))
+ {
+ G_sgpe_stop_record.group.quad[VECTOR_BLOCKX] |= BIT32(qloop);
+ }
+ else
+ {
+ G_sgpe_stop_record.group.quad[VECTOR_BLOCKX] &= ~BIT32(qloop);
+ }
+ }
+ // not participate exit, taking exit encoding bit out
+ else
+ {
+ action = action & (~BIT32(6));
+ }
+
+ // target quad is to participate block/unblock entry
+ if (scom_data.words.upper & BIT32(11))
+ {
+ action = action | BIT32(7);
+
+ if (action & BIT32(5))
+ {
+ G_sgpe_stop_record.group.quad[VECTOR_BLOCKE] |= BIT32(qloop);
+ }
+ else
+ {
+ G_sgpe_stop_record.group.quad[VECTOR_BLOCKE] &= ~BIT32(qloop);
+ }
+ }
+ // not participate entry, taking entry encoding bit out
+ else
+ {
+ action = action & (~BIT32(7));
+ }
+
+ // if this quad participates either entry/exit for block/unlock
+ // send msg; otherwise skip the quad
+ if (action & BITS32(6, 2))
+ {
+ p9_sgpe_stop_suspend_msg_db1(qloop, action);
+ }
+ }
+ }
+
+ pk_irq_vec_restore(&ctx);
+}
+
+
+
// PCB Interrupt Type2
// Payload
// 0 - set = Hardware Exit | unset = Firmware Stop
@@ -86,17 +224,20 @@ void
p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
{
PkMachineContext ctx;
- uint32_t cirq = 0;
- uint32_t qirq = 0;
- uint32_t cloop = 0;
- uint32_t qloop = 0;
- uint32_t cpending_t2 = 0;
- uint32_t cpending_t3 = 0;
- uint32_t qpending_t6 = 0;
- uint32_t cpayload_t2 = 0;
- uint32_t cpayload_t3 = 0;
- uint32_t qpayload_t6 = 0;
- uint64_t scom_data = 0;
+ uint32_t cirq = 0;
+ uint32_t qirq = 0;
+ uint32_t cloop = 0;
+ uint32_t qloop = 0;
+ uint32_t cpending_t2 = 0;
+ uint32_t cpending_t3 = 0;
+ uint32_t qpending_t6 = 0;
+ uint32_t cpayload_t2 = 0;
+ uint32_t cpayload_t3 = 0;
+ uint32_t qpayload_t6 = 0;
+ uint32_t suspend_mask = 0;
+ uint32_t suspend_index = 0;
+ uint32_t vector_index = 0;
+ data64_t scom_data = {0};
//=========================
MARK_TRAP(STOP_PIG_HANDLER)
@@ -136,19 +277,15 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
}
// clear group before analyzing input
- G_sgpe_stop_record.group.qswu[VECTOR_ENTRY] = 0;
G_sgpe_stop_record.group.core[VECTOR_ENTRY] = 0;
- G_sgpe_stop_record.group.qswu[VECTOR_EXIT] = 0;
+ G_sgpe_stop_record.group.qswu[VECTOR_ENTRY] = 0;
G_sgpe_stop_record.group.core[VECTOR_EXIT] = 0;
- G_sgpe_stop_record.group.ex_l[VECTOR_EXIT] = 0;
- G_sgpe_stop_record.group.ex_r[VECTOR_EXIT] = 0;
- G_sgpe_stop_record.group.ex_b[VECTOR_EXIT] = 0;
+ G_sgpe_stop_record.group.qswu[VECTOR_EXIT] = 0;
G_sgpe_stop_record.group.quad[VECTOR_EXIT] = 0;
// loop all quads
for(qloop = 0; qloop < MAX_QUADS; qloop++)
{
-
// if no quad special wakeup, skip to core request
if (qirq && (BIT32(qloop) & qpending_t6 &
G_sgpe_stop_record.group.quad[VECTOR_CONFIG]))
@@ -166,14 +303,15 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
{
PK_TRACE_DBG("Quad Already in Special Wakeup");
}
+ else if (G_sgpe_stop_record.group.quad[VECTOR_BLOCKX] & BIT32(qloop))
+ {
+ PK_TRACE_DBG("Quad is in Block Wakeup Mode, Ignore Now");
+ G_sgpe_stop_record.group.qswu[VECTOR_BLOCKX] |= BIT32(qloop);
+ }
else
{
G_sgpe_stop_record.group.qswu[VECTOR_EXIT] |= BIT32(qloop);
G_sgpe_stop_record.group.quad[VECTOR_EXIT] |= BIT32(qloop);
- G_sgpe_stop_record.group.ex_l[VECTOR_EXIT] |= BIT32(qloop);
- G_sgpe_stop_record.group.ex_r[VECTOR_EXIT] |= BIT32(qloop);
- G_sgpe_stop_record.group.ex_b[VECTOR_EXIT] |=
- BITS32((qloop << 1), 2);
}
}
else
@@ -181,8 +319,16 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
PK_TRACE_DBG("Quad Drop Special Wakeup, Clearing Done");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_GPMMR_CLR, qloop), BIT64(0));
- G_sgpe_stop_record.group.qswu[VECTOR_ENTRY] |= BIT32(qloop);
- G_sgpe_stop_record.group.qswu[VECTOR_CONFIG] &= ~BIT32(qloop);
+ if (G_sgpe_stop_record.group.quad[VECTOR_BLOCKE] & BIT32(qloop))
+ {
+ PK_TRACE_DBG("Quad is in Block Entry Mode, Ignore Re-entry Now");
+ G_sgpe_stop_record.group.qswu[VECTOR_BLOCKE] |= BIT32(qloop);
+ }
+ else
+ {
+ G_sgpe_stop_record.group.qswu[VECTOR_ENTRY] |= BIT32(qloop);
+ G_sgpe_stop_record.group.qswu[VECTOR_CONFIG] &= ~BIT32(qloop);
+ }
}
}
@@ -194,7 +340,7 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
}
PK_TRACE_DBG("Quad[%d] Has Core Request:", qloop);
- PK_TRACE_DBG("Now clv[%d][%d][%d][%d]",
+ PK_TRACE_DBG("Now Core Levels[%d][%d][%d][%d]",
G_sgpe_stop_record.level[qloop][0],
G_sgpe_stop_record.level[qloop][1],
G_sgpe_stop_record.level[qloop][2],
@@ -209,10 +355,10 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
continue;
}
- // read payload on core has interrupt2 cpending
cpayload_t2 = 0;
cpayload_t3 = 0;
+ // read payload on core has interrupt2 cpending
if (cpending_t2 & BIT32((qloop << 2) + cloop))
{
cpayload_t2 = in32(OCB_OPIT2CN(((qloop << 2) + cloop)));
@@ -227,8 +373,73 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
PK_TRACE_INF("Core[%d] Type2 Payload [%x] Type3 Payload [%x]",
((qloop << 2) + cloop), cpayload_t2, cpayload_t3);
+ // if not hardware pig and is an suspend ack pig
+ if (((~cpayload_t2) & TYPE2_PAYLOAD_HARDWARE_WAKEUP) &&
+ (cpayload_t2 & TYPE2_PAYLOAD_SUSPEND_ACK_MASK))
+ {
+ for(suspend_mask = TYPE2_PAYLOAD_SUSPEND_EXIT_MASK,
+ vector_index = VECTOR_EXIT,
+ suspend_index = VECTOR_BLOCKX;
+ suspend_index > 0;
+ suspend_index--,
+ vector_index--,
+ suspend_mask = suspend_mask >> 1)
+ {
+ // if entry/exit is selected for performing suspend/unsuspend operation
+ if (cpayload_t2 & suspend_mask)
+ {
+ // suspend entry/exit/both
+ if (cpayload_t2 & TYPE2_PAYLOAD_SUSPEND_OP_MASK)
+ {
+ if ((cloop >> 1) % 2)
+ {
+ G_sgpe_stop_record.group.ex_r[suspend_index] |= BIT32(qloop);
+ }
+ else
+ {
+ G_sgpe_stop_record.group.ex_l[suspend_index] |= BIT32(qloop);
+ }
+
+ if((G_sgpe_stop_record.group.ex_r[suspend_index] &
+ G_sgpe_stop_record.group.ex_l[suspend_index] &
+ G_sgpe_stop_record.group.quad[suspend_index]) ==
+ G_sgpe_stop_record.group.quad[suspend_index])
+ {
+ out32(OCB_OCCFLG_CLR, BIT32(SGPE_IGNORE_STOP_CONTROL));
+ }
+ }
+ // unsuspend entry/exit/both
+ else
+ {
+ if ((cloop >> 1) % 2)
+ {
+ G_sgpe_stop_record.group.ex_r[suspend_index] &= ~BIT32(qloop);
+ }
+ else
+ {
+ G_sgpe_stop_record.group.ex_l[suspend_index] &= ~BIT32(qloop);
+ }
+
+ if ((G_sgpe_stop_record.group.ex_r[suspend_index] |
+ G_sgpe_stop_record.group.ex_l[suspend_index]) == 0)
+ {
+ G_sgpe_stop_record.group.core[vector_index] |=
+ G_sgpe_stop_record.group.core[suspend_index];
+ G_sgpe_stop_record.group.core[suspend_index] = 0;
+ G_sgpe_stop_record.group.qswu[vector_index] |=
+ G_sgpe_stop_record.group.qswu[suspend_index];
+ G_sgpe_stop_record.group.qswu[suspend_index] = 0;
+ out32(OCB_OCCFLG_CLR, BIT32(SGPE_IGNORE_STOP_CONTROL));
+ }
+ }
+ }
+ }
+
+ continue;
+ }
+
GPE_GETSCOM(GPE_SCOM_ADDR_CORE(CPPM_CPMMR,
- ((qloop << 2) + cloop)), scom_data);
+ ((qloop << 2) + cloop)), scom_data.value);
// T2 T3 NS given point to SGPE
// exit exit SGPE ---- proceed with exit
@@ -270,7 +481,7 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
// if t2 entry (t3 exit or empty)
else if (cpayload_t2 && (!(cpayload_t2 & TYPE2_PAYLOAD_EXIT_EVENT)))
{
- if (!(scom_data & BIT64(13)))
+ if (!(scom_data.words.upper & BIT32(13)))
{
// wakeup=normal + notify=cme -> error
if (cpayload_t2 != 0x400)
@@ -300,7 +511,7 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
// if t3 entry (t2 exit or empty)
else if (cpayload_t3 && (!(cpayload_t3 & TYPE2_PAYLOAD_EXIT_EVENT)))
{
- if (!(scom_data & BIT64(13)))
+ if (!(scom_data.words.upper & BIT32(13)))
{
PK_TRACE_ERR("ERROR: Received Type3 Entry PIG When Wakeup_notify_select = 0. HALT SGPE!");
PK_PANIC(SGPE_PIG_TYPE3_ENTRY_WNS_CME);
@@ -315,7 +526,7 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
// both exit or one exit + one empty
else
{
- if (!(scom_data & BIT64(13)))
+ if (!(scom_data.words.upper & BIT32(13)))
{
if ((cpayload_t2 & TYPE2_PAYLOAD_EXIT_EVENT) &&
(cpayload_t3 & TYPE2_PAYLOAD_EXIT_EVENT))
@@ -332,25 +543,20 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
{
PK_TRACE_INF("Core Request Exit");
- if (cloop < CORES_PER_EX)
+ if (G_sgpe_stop_record.group.quad[VECTOR_BLOCKX] & BIT32(qloop))
{
- G_sgpe_stop_record.group.ex_l[VECTOR_EXIT] |=
- BIT32(qloop);
- G_sgpe_stop_record.group.ex_b[VECTOR_EXIT] |=
- BIT32((qloop << 1));
+ PK_TRACE_DBG("Core is in Block Wakeup Mode, Ignore Now", cloop);
+ G_sgpe_stop_record.group.core[VECTOR_BLOCKX] |=
+ BIT32(((qloop << 2) + cloop));
}
else
{
- G_sgpe_stop_record.group.ex_r[VECTOR_EXIT] |=
+ PK_TRACE_DBG("Core Considered Stopped, Will Wakeup", cloop);
+ G_sgpe_stop_record.group.quad[VECTOR_EXIT] |=
BIT32(qloop);
- G_sgpe_stop_record.group.ex_b[VECTOR_EXIT] |=
- BIT32(((qloop << 1) + 1));
+ G_sgpe_stop_record.group.core[VECTOR_EXIT] |=
+ BIT32(((qloop << 2) + cloop));
}
-
- G_sgpe_stop_record.group.quad[VECTOR_EXIT] |=
- BIT32(qloop);
- G_sgpe_stop_record.group.core[VECTOR_EXIT] |=
- BIT32(((qloop << 2) + cloop));
}
}
}
@@ -362,13 +568,6 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
G_sgpe_stop_record.level[qloop][3]);
}
- G_sgpe_stop_record.group.ex_b[VECTOR_EXIT] &=
- G_sgpe_stop_record.group.ex_b[VECTOR_CONFIG];
- G_sgpe_stop_record.group.ex_l[VECTOR_EXIT] &=
- G_sgpe_stop_record.group.ex_l[VECTOR_CONFIG];
- G_sgpe_stop_record.group.ex_r[VECTOR_EXIT] &=
- G_sgpe_stop_record.group.ex_r[VECTOR_CONFIG];
-
PK_TRACE_DBG("Quad Special Wakeup: Raise[%x], Drop[%x]",
G_sgpe_stop_record.group.qswu[VECTOR_EXIT],
G_sgpe_stop_record.group.qswu[VECTOR_ENTRY]);
@@ -402,5 +601,8 @@ p9_sgpe_stop_pig_handler(void* arg, PkIrqId irq)
G_sgpe_stop_record.wof.status_stop = STATUS_PROCESSING;
pk_semaphore_post(&(G_sgpe_stop_record.sem[0]));
}
+
+ PK_TRACE("Disable ipi3_lo interrupt");
+ out32(OCB_OIMR1_OR, BIT32(29));
}
}
OpenPOWER on IntegriCloud