diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-11-21 20:32:23 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-11-28 20:39:07 -0600 |
commit | d7e26801905f40d807ce60bc99ed511e91549f1e (patch) | |
tree | 856716595f019ad0312f2902973324193f960212 /hw/xive.c | |
parent | 9ce34f369ce2412cb68052717e457d1e78eedb75 (diff) | |
download | skiboot-d7e26801905f40d807ce60bc99ed511e91549f1e.zip skiboot-d7e26801905f40d807ce60bc99ed511e91549f1e.tar.gz skiboot-d7e26801905f40d807ce60bc99ed511e91549f1e.tar.bz2 |
xive: When disabling an EQ, wipe all of its settings
This avoids having configuration bits left over
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/xive.c')
-rw-r--r-- | hw/xive.c | 101 |
1 files changed, 51 insertions, 50 deletions
@@ -3983,61 +3983,62 @@ static int64_t opal_xive_set_queue_info(uint64_t vp, uint32_t prio, */ eq = *old_eq; - switch(qsize) { - /* Supported sizes */ - case 12: - case 16: - case 21: - case 24: - eq.w3 = ((uint64_t)qpage) & 0xffffffff; - eq.w2 = (((uint64_t)qpage)) >> 32 & 0x0fffffff; - eq.w0 |= EQ_W0_ENQUEUE; - eq.w0 = SETFIELD(EQ_W0_QSIZE, eq.w0, qsize - 12); - break; - case 0: - eq.w2 = eq.w3 = 0; - eq.w0 &= ~EQ_W0_ENQUEUE; - break; - default: - return OPAL_PARAMETER; - } - - /* Ensure the priority and target are correctly set (they will - * not be right after allocation - */ - eq.w6 = SETFIELD(EQ_W6_NVT_BLOCK, 0ul, vp_blk) | - SETFIELD(EQ_W6_NVT_INDEX, 0ul, vp_idx); - eq.w7 = SETFIELD(EQ_W7_F0_PRIORITY, 0ul, prio); - /* XXX Handle group i bit when needed */ + if (qflags & OPAL_XIVE_EQ_ENABLED) { + switch(qsize) { + /* Supported sizes */ + case 12: + case 16: + case 21: + case 24: + eq.w3 = ((uint64_t)qpage) & 0xffffffff; + eq.w2 = (((uint64_t)qpage)) >> 32 & 0x0fffffff; + eq.w0 |= EQ_W0_ENQUEUE; + eq.w0 = SETFIELD(EQ_W0_QSIZE, eq.w0, qsize - 12); + break; + case 0: + eq.w2 = eq.w3 = 0; + eq.w0 &= ~EQ_W0_ENQUEUE; + break; + default: + return OPAL_PARAMETER; + } - /* Always notify flag */ - if (qflags & OPAL_XIVE_EQ_ALWAYS_NOTIFY) - eq.w0 |= EQ_W0_UCOND_NOTIFY; - else - eq.w0 &= ~EQ_W0_UCOND_NOTIFY; + /* Ensure the priority and target are correctly set (they will + * not be right after allocation + */ + eq.w6 = SETFIELD(EQ_W6_NVT_BLOCK, 0ul, vp_blk) | + SETFIELD(EQ_W6_NVT_INDEX, 0ul, vp_idx); + eq.w7 = SETFIELD(EQ_W7_F0_PRIORITY, 0ul, prio); + /* XXX Handle group i bit when needed */ + + /* Always notify flag */ + if (qflags & OPAL_XIVE_EQ_ALWAYS_NOTIFY) + eq.w0 |= EQ_W0_UCOND_NOTIFY; + else + eq.w0 &= ~EQ_W0_UCOND_NOTIFY; - /* Escalation flag */ - if (qflags & OPAL_XIVE_EQ_ESCALATE) - eq.w0 |= EQ_W0_ESCALATE_CTL; - else - eq.w0 &= ~EQ_W0_ESCALATE_CTL; + /* Escalation flag */ + if (qflags & OPAL_XIVE_EQ_ESCALATE) + eq.w0 |= EQ_W0_ESCALATE_CTL; + else + eq.w0 &= ~EQ_W0_ESCALATE_CTL; - /* Unconditionally clear the current queue pointer, set - * generation to 1 and disable escalation interrupts. - */ - eq.w1 = EQ_W1_GENERATION | - (old_eq->w1 & (EQ_W1_ESe_P | EQ_W1_ESe_Q | - EQ_W1_ESn_P | EQ_W1_ESn_Q)); + /* Unconditionally clear the current queue pointer, set + * generation to 1 and disable escalation interrupts. + */ + eq.w1 = EQ_W1_GENERATION | + (old_eq->w1 & (EQ_W1_ESe_P | EQ_W1_ESe_Q | + EQ_W1_ESn_P | EQ_W1_ESn_Q)); - /* Enable or disable. We always enable backlog for an - * enabled queue otherwise escalations won't work. - */ - if (qflags & OPAL_XIVE_EQ_ENABLED) + /* Enable. We always enable backlog for an enabled queue + * otherwise escalations won't work. + */ eq.w0 |= EQ_W0_VALID | EQ_W0_BACKLOG; - else { - eq.w0 &= ~EQ_W0_VALID; - eq.w1 &= ~(EQ_W1_ESe_P | EQ_W1_ESn_P); - eq.w1 |= EQ_W1_ESe_Q | EQ_W1_ESn_Q; + } else { + /* Clear everything and set PQ bits to 01 */ + eq.w0 = old_eq->w0 & EQ_W0_FIRMWARE; + eq.w1 = EQ_W1_ESe_Q | EQ_W1_ESn_Q; + eq.w2 = eq.w3 = eq.w4 = eq.w5 = eq.w6 = eq.w7 = 0; } /* Update EQ, non-synchronous */ |