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 | |
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>
-rw-r--r-- | doc/xive.rst | 10 | ||||
-rw-r--r-- | hw/xive.c | 101 |
2 files changed, 58 insertions, 53 deletions
diff --git a/doc/xive.rst b/doc/xive.rst index c4f4950..85fe111 100644 --- a/doc/xive.rst +++ b/doc/xive.rst @@ -565,14 +565,18 @@ and priority and adjust the behaviour of the queue via flags. .. note:: This call will reset the generation bit to 1 and the queue production pointer to 0. - .. note:: The PQ bits of the escalation interrupts will be set to 00 - when OPAL_XIVE_EQ_ENABLED is set, and to 01 (masked) when - disabling it. + .. note:: The PQ bits of the escalation interrupts and of the queue + notification will be set to 00 when OPAL_XIVE_EQ_ENABLED is + set, and to 01 (masked) when disabling it. .. note:: This must be called at least once on a queue with the flag OPAL_XIVE_EQ_ENABLED in order to enable it after it has been allocated (along with its owner VP). + .. note:: When the queue is disabled (flag OPAL_XIVE_EQ_ENABLED cleared) + all other flags and arguments are ignored and the queue + configuration is wiped. + OPAL_XIVE_DONATE_PAGE ^^^^^^^^^^^^^^^^^^^^^ .. code-block:: c @@ -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 */ |